@@ -18,6 +18,9 @@ func NewStore(db *sql.DB) *Store {
1818 return & Store {db : db }
1919}
2020
21+ const eventColumns = `id, delivery_id, dedup_key, source, type, actor, subject,
22+ attrs, raw, state, worker_name, task_id, created_at, updated_at`
23+
2124// Create persists a new event in received state.
2225func (s * Store ) Create (ctx context.Context , ev * Event ) error {
2326 if ev .ID == "" {
@@ -32,17 +35,17 @@ func (s *Store) Create(ctx context.Context, ev *Event) error {
3235 ev .CreatedAt = now
3336 ev .UpdatedAt = now
3437
35- payload , err := json .Marshal (ev .Payload )
38+ attrs , err := json .Marshal (ev .Attrs )
3639 if err != nil {
37- return fmt .Errorf ("marshal event payload : %w" , err )
40+ return fmt .Errorf ("marshal event attrs : %w" , err )
3841 }
3942
4043 _ , err = s .db .ExecContext (ctx ,
41- `INSERT INTO events (id, delivery_id, source, type, repo_owner, repo_name ,
42- ref, number, sender, payload , raw, state, created_at, updated_at)
43- VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,? )` ,
44- ev .ID , ev .DeliveryID , ev .Source , ev .Type , ev .RepoOwner , ev .RepoName ,
45- ev . Ref , ev . Number , ev . Sender , string (payload ), string (ev .Raw ),
44+ `INSERT INTO events (id, delivery_id, dedup_key, source, type, actor, subject ,
45+ attrs , raw, state, created_at, updated_at)
46+ VALUES (?,?,?,?,?,?,?,?,?,?,?,?)` ,
47+ ev .ID , ev .DeliveryID , ev .DedupKey , ev . Source , ev .Type , ev .Actor , ev .Subject ,
48+ string (attrs ), string (ev .Raw ),
4649 string (ev .State ), now .Unix (), now .Unix (),
4750 )
4851 if err != nil {
@@ -69,17 +72,13 @@ func (s *Store) DeliveryExists(ctx context.Context, deliveryID string) (bool, er
6972// Get retrieves an event by ID.
7073func (s * Store ) Get (ctx context.Context , id string ) (* Event , error ) {
7174 row := s .db .QueryRowContext (ctx ,
72- `SELECT id, delivery_id, source, type, repo_owner, repo_name,
73- ref, number, sender, payload, raw, state, worker_name, task_id,
74- created_at, updated_at FROM events WHERE id = ?` , id )
75+ `SELECT ` + eventColumns + ` FROM events WHERE id = ?` , id )
7576 return scanEvent (row )
7677}
7778
7879// List returns events, optionally filtered by state.
7980func (s * Store ) List (ctx context.Context , state string ) ([]Event , error ) {
80- query := `SELECT id, delivery_id, source, type, repo_owner, repo_name,
81- ref, number, sender, payload, raw, state, worker_name, task_id,
82- created_at, updated_at FROM events`
81+ query := `SELECT ` + eventColumns + ` FROM events`
8382 var args []any
8483 if state != "" {
8584 query += " WHERE state = ?"
@@ -102,6 +101,22 @@ func (s *Store) List(ctx context.Context, state string) ([]Event, error) {
102101 return events , rows .Err ()
103102}
104103
104+ // UpdateAttrs persists hydrated attrs back to the database.
105+ func (s * Store ) UpdateAttrs (ctx context.Context , id string , attrs Attrs ) error {
106+ data , err := json .Marshal (attrs )
107+ if err != nil {
108+ return fmt .Errorf ("marshal attrs: %w" , err )
109+ }
110+ now := time .Now ().Unix ()
111+ res , err := s .db .ExecContext (ctx ,
112+ "UPDATE events SET attrs = ?, updated_at = ? WHERE id = ?" ,
113+ string (data ), now , id )
114+ if err != nil {
115+ return fmt .Errorf ("update attrs: %w" , err )
116+ }
117+ return checkRows (res , id , "update attrs" )
118+ }
119+
105120// SetMatched transitions received → matched with worker name.
106121func (s * Store ) SetMatched (ctx context.Context , id , workerName string ) error {
107122 return s .transitionWithExtra (ctx , id , StateReceived , StateMatched , workerName ,
@@ -138,6 +153,27 @@ func (s *Store) SetSkipped(ctx context.Context, id string) error {
138153 "UPDATE events SET state = ?, updated_at = ? WHERE id = ? AND state = ?" )
139154}
140155
156+ // Received returns IDs of events stuck in received state (for crash recovery).
157+ func (s * Store ) Received (ctx context.Context ) ([]string , error ) {
158+ rows , err := s .db .QueryContext (ctx ,
159+ `SELECT id FROM events WHERE state = ? ORDER BY created_at` ,
160+ string (StateReceived ),
161+ )
162+ if err != nil {
163+ return nil , fmt .Errorf ("query received: %w" , err )
164+ }
165+ defer rows .Close ()
166+ var ids []string
167+ for rows .Next () {
168+ var id string
169+ if err := rows .Scan (& id ); err != nil {
170+ return nil , err
171+ }
172+ ids = append (ids , id )
173+ }
174+ return ids , rows .Err ()
175+ }
176+
141177func (s * Store ) transition (ctx context.Context , id string , from , to State , query string ) error {
142178 now := time .Now ().Unix ()
143179 res , err := s .db .ExecContext (ctx , query , string (to ), now , id , string (from ))
@@ -155,4 +191,3 @@ func (s *Store) transitionWithExtra(ctx context.Context, id string, from, to Sta
155191 }
156192 return checkRows (res , id , string (to ))
157193}
158-
0 commit comments