Skip to content

Commit 5f7ab76

Browse files
committed
fix(stovepipe): use Get+Create for queue row in ingest
Replace the missing QueueStore.GetOrCreate call with ensureQueue, matching the ensureRequest pattern used elsewhere in the ingest controller.
1 parent efea1c0 commit 5f7ab76

2 files changed

Lines changed: 34 additions & 9 deletions

File tree

stovepipe/controller/ingest.go

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -215,15 +215,42 @@ func (c *IngestController) ensureRequest(ctx context.Context, id, queue, uri str
215215
return request, nil
216216
}
217217

218+
// ensureQueue returns the queue row for name, creating it if it does not yet exist.
219+
// A concurrent creator (ErrAlreadyExists) is resolved by re-reading the canonical row.
220+
func (c *IngestController) ensureQueue(ctx context.Context, name string) (entity.Queue, error) {
221+
queueStore := c.store.GetQueueStore()
222+
223+
got, err := queueStore.Get(ctx, name)
224+
if err == nil {
225+
return got, nil
226+
}
227+
if !errors.Is(err, storage.ErrNotFound) {
228+
return entity.Queue{}, fmt.Errorf("IngestController failed to load queue %s: %w", name, err)
229+
}
230+
231+
queue := entity.Queue{
232+
Name: name,
233+
Version: 1,
234+
}
235+
if err := queueStore.Create(ctx, queue); err != nil {
236+
if !errors.Is(err, storage.ErrAlreadyExists) {
237+
return entity.Queue{}, fmt.Errorf("IngestController failed to persist queue %s: %w", name, err)
238+
}
239+
// Raced with a concurrent creator; read the canonical row.
240+
return queueStore.Get(ctx, name)
241+
}
242+
return queue, nil
243+
}
244+
218245
// advanceQueueLatestRequestID CAS-updates queue.latest_request_id to id when id is newer.
219246
// Retries on optimistic-lock conflicts so concurrent ingests converge.
220247
func (c *IngestController) advanceQueueLatestRequestID(ctx context.Context, queue, id string) error {
221248
queueStore := c.store.GetQueueStore()
222249

223250
for {
224-
queueRow, err := queueStore.GetOrCreate(ctx, queue, entity.Queue{Version: 1})
251+
queueRow, err := c.ensureQueue(ctx, queue)
225252
if err != nil {
226-
return fmt.Errorf("IngestController failed to load queue %s: %w", queue, err)
253+
return err
227254
}
228255
if queueRow.LatestRequestID != "" {
229256
cmp, err := entity.CompareRequestID(queue, id, queueRow.LatestRequestID)

stovepipe/controller/ingest_test.go

Lines changed: 5 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -88,19 +88,17 @@ func expectResolve(m ingestMocks) {
8888
m.sc.EXPECT().Latest(gomock.Any()).Return(testURI, nil)
8989
}
9090

91-
// expectAdvanceLatestRequestID wires GetOrCreate + Update for queue.latest_request_id.
91+
// expectAdvanceLatestRequestID wires Get + Create + Update for queue.latest_request_id.
9292
func expectAdvanceLatestRequestID(m ingestMocks, queue, id string) {
93-
m.queueStore.EXPECT().GetOrCreate(gomock.Any(), queue, entity.Queue{Version: 1}).Return(entity.Queue{
94-
Name: queue,
95-
Version: 1,
96-
}, nil)
93+
m.queueStore.EXPECT().Get(gomock.Any(), queue).Return(entity.Queue{}, storage.ErrNotFound)
94+
m.queueStore.EXPECT().Create(gomock.Any(), entity.Queue{Name: queue, Version: 1}).Return(nil)
9795
updated := entity.Queue{Name: queue, LatestRequestID: id, Version: 1}
9896
m.queueStore.EXPECT().Update(gomock.Any(), updated, int32(1), int32(2)).Return(nil)
9997
}
10098

101-
// expectAdvanceLatestRequestIDNoOp wires GetOrCreate when latest_request_id is already at id.
99+
// expectAdvanceLatestRequestIDNoOp wires Get when latest_request_id is already at id.
102100
func expectAdvanceLatestRequestIDNoOp(m ingestMocks, queue, id string) {
103-
m.queueStore.EXPECT().GetOrCreate(gomock.Any(), queue, entity.Queue{Version: 1}).Return(entity.Queue{
101+
m.queueStore.EXPECT().Get(gomock.Any(), queue).Return(entity.Queue{
104102
Name: queue,
105103
LatestRequestID: id,
106104
Version: 1,

0 commit comments

Comments
 (0)