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

Function writeOutboxRow

internal/webhookpub/outbox.go:182–254  ·  view source on GitHub ↗

writeOutboxRow is the SQL body shared by PublishTx and (eventually) PublishBestEffortTx. Idempotent on (id): a retried trigger with the same deterministic id no-ops the second INSERT. Issues pg_notify so the slice-2 worker wakes immediately on commit.

(ctx context.Context, exec outboxExecutor, e Event)

Source from the content-addressed store, hash-verified

180// same deterministic id no-ops the second INSERT. Issues pg_notify so
181// the slice-2 worker wakes immediately on commit.
182func writeOutboxRow(ctx context.Context, exec outboxExecutor, e Event) error {
183 if e.ID == "" {
184 return fmt.Errorf("webhookpub: outbox event must have non-empty ID")
185 }
186 if e.UserID == "" {
187 return fmt.Errorf("webhookpub: outbox event must have non-empty UserID")
188 }
189 if e.Type == "" {
190 return fmt.Errorf("webhookpub: outbox event must have non-empty Type")
191 }
192
193 envelopeJSON, err := json.Marshal(e.AsEnvelope())
194 if err != nil {
195 return fmt.Errorf("webhookpub: marshal envelope: %w", err)
196 }
197
198 var messageID *string
199 if e.MessageID != "" {
200 mid := e.MessageID
201 messageID = &mid
202 }
203 var agentID *string
204 if e.AgentID != "" {
205 aid := e.AgentID
206 agentID = &aid
207 }
208 var conversationID *string
209 if e.ConversationID != "" {
210 cid := e.ConversationID
211 conversationID = &cid
212 }
213
214 // created_at and expires_at use the column DEFAULTs so the
215 // timestamps come from the Postgres server clock (one clock per
216 // primary writer; no application-side skew).
217 _, err = exec.Exec(ctx,
218 `INSERT INTO webhook_events
219 (id, user_id, type, aud, envelope, schema_version,
220 agent_id, conversation_id, message_id, status)
221 VALUES ($1, $2, $3, 'webhook', $4, 1, $5, $6, $7, 'pending')
222 ON CONFLICT (id) DO NOTHING`,
223 e.ID, e.UserID, e.Type, envelopeJSON,
224 agentID, conversationID, messageID,
225 )
226 if err != nil {
227 return fmt.Errorf("webhookpub: insert webhook_events: %w", err)
228 }
229
230 // pg_notify is best-effort: NOTIFY only fires on COMMIT (Postgres
231 // queues it). If COMMIT fails, no notification is emitted. The
232 // slice-2 worker's 1s fallback poll catches missed wakeups
233 // (deploy windows, LISTEN reconnect races). Payload is empty
234 // because the worker rescans the table anyway.
235 //
236 // A pg_notify error here (NOTIFY queue overflow is the realistic
237 // case; max_notify_queue_pages defaults to 1024 × 8KB = 8MB) is a
238 // SOFT failure: we log and return nil so the caller's tx still
239 // commits. The webhook_events row is what matters for at-least-

Calls 2

AsEnvelopeMethod · 0.80
ExecMethod · 0.65