MCPcopy Create free account
hub / github.com/Mnexa-AI/e2a / ModifyMessageLabels

Method ModifyMessageLabels

internal/identity/store.go:2631–2690  ·  view source on GitHub ↗

ModifyMessageLabels applies a delta — add then remove — to a message's labels[] in a single atomic statement. Returns the updated labels (deduplicated, sorted) so the caller can echo them back in the response without a second round-trip. Inputs are assumed already normalized (lowercased, charset-va

(ctx context.Context, messageID, agentID string, add, remove []string)

Source from the content-addressed store, hash-verified

2629// The whole thing runs as one UPDATE so a concurrent PATCH from a
2630// second client can't observe a partial state.
2631func (s *Store) ModifyMessageLabels(ctx context.Context, messageID, agentID string, add, remove []string) ([]string, error) {
2632 // Pre-check the post-add length against the cap. Done as a
2633 // dedicated SELECT-then-UPDATE so we can return a specific error
2634 // rather than a generic constraint violation — the handler maps
2635 // ErrLabelLimitExceeded to 400 with a useful message.
2636 tx, err := s.pool.Begin(ctx)
2637 if err != nil {
2638 return nil, err
2639 }
2640 defer tx.Rollback(ctx)
2641
2642 var current []string
2643 err = tx.QueryRow(ctx,
2644 `SELECT labels FROM messages WHERE id = $1 AND agent_id = $2 AND expires_at > now() AND NOT (direction = 'inbound' AND status IN (`+heldInboundStatuses+`)) FOR UPDATE`,
2645 messageID, agentID,
2646 ).Scan(&current)
2647 if err != nil {
2648 if errors.Is(err, pgx.ErrNoRows) {
2649 return nil, ErrMessageNotFound
2650 }
2651 return nil, err
2652 }
2653
2654 // Apply the delta in-memory so the cap check is exact. The set
2655 // semantics here mirror what the SQL UPDATE below does:
2656 // labels' = (labels ∪ add) \ remove.
2657 labelSet := map[string]struct{}{}
2658 for _, l := range current {
2659 labelSet[l] = struct{}{}
2660 }
2661 for _, l := range add {
2662 labelSet[l] = struct{}{}
2663 }
2664 for _, l := range remove {
2665 delete(labelSet, l)
2666 }
2667 if len(labelSet) > MaxLabelsPerMessage {
2668 return nil, ErrLabelLimitExceeded
2669 }
2670
2671 final := make([]string, 0, len(labelSet))
2672 for l := range labelSet {
2673 final = append(final, l)
2674 }
2675 sort.Strings(final)
2676
2677 if _, err := tx.Exec(ctx,
2678 `UPDATE messages SET labels = $1 WHERE id = $2 AND agent_id = $3 AND NOT (direction = 'inbound' AND status IN (`+heldInboundStatuses+`))`,
2679 final, messageID, agentID,
2680 ); err != nil {
2681 return nil, err
2682 }
2683 if err := tx.Commit(ctx); err != nil {
2684 return nil, err
2685 }
2686 if final == nil {
2687 final = []string{}
2688 }

Implementers 1

Storeinternal/identity/store.go

Calls 6

makeFunction · 0.85
RollbackMethod · 0.80
ScanMethod · 0.80
QueryRowMethod · 0.80
CommitMethod · 0.80
ExecMethod · 0.65