@@ -29,7 +29,6 @@ import (
2929 queuemock "github.com/uber/submitqueue/platform/extension/messagequeue/mock"
3030 "github.com/uber/submitqueue/submitqueue/core/topickey"
3131 "github.com/uber/submitqueue/submitqueue/entity"
32- "github.com/uber/submitqueue/submitqueue/extension/storage"
3332 storagemock "github.com/uber/submitqueue/submitqueue/extension/storage/mock"
3433 "go.uber.org/mock/gomock"
3534 "go.uber.org/zap"
@@ -58,27 +57,29 @@ func newCancelTestRegistryWithNoopPublisher(t *testing.T, ctrl *gomock.Controlle
5857 return registry
5958}
6059
61- // newRequestLogStoreNoop returns a RequestLogStore mock whose List returns a single
62- // dummy entry (so existence check passes) and whose Insert silently succeeds for any input.
63- func newRequestLogStoreNoop (t * testing.T , ctrl * gomock.Controller ) * storagemock.MockRequestLogStore {
64- t .Helper ()
65- store := storagemock .NewMockRequestLogStore (ctrl )
66- store .EXPECT ().List (gomock .Any (), gomock .Any ()).Return ([]entity.RequestLog {{}}, nil ).AnyTimes ()
67- store .EXPECT ().Insert (gomock .Any (), gomock .Any ()).Return (nil ).AnyTimes ()
68- return store
60+ // newCancelStorageFixture returns a storage fixture with one received request.
61+ func newCancelStorageFixture (ctrl * gomock.Controller , requestID string ) * controllerStorageFixture {
62+ fixture := newControllerStorageFixture (ctrl )
63+ if requestID != "" {
64+ fixture .addSummary (entity.RequestSummary {
65+ RequestID : requestID , Queue : "test-queue" , ChangeURIs : []string {}, ReceivedAtMs : 1 ,
66+ Status : entity .RequestStatusAccepted , StatusTimestampMs : 1 , Version : 1 , Metadata : map [string ]string {},
67+ })
68+ }
69+ return fixture
6970}
7071
7172func TestNewCancelController (t * testing.T ) {
7273 ctrl := gomock .NewController (t )
7374
74- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newRequestLogStoreNoop ( t , ctrl ) , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
75+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newCancelStorageFixture ( ctrl , "test-queue/42" ). storage , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
7576 require .NotNil (t , controller )
7677}
7778
7879func TestCancel_HappyPath (t * testing.T ) {
7980 ctrl := gomock .NewController (t )
8081
81- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newRequestLogStoreNoop ( t , ctrl ) , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
82+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newCancelStorageFixture ( ctrl , "test-queue/42" ). storage , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
8283 ctx := context .Background ()
8384
8485 req := & pb.CancelRequest {Sqid : "test-queue/42" , Reason : "user changed their mind" }
@@ -91,7 +92,7 @@ func TestCancel_HappyPath(t *testing.T) {
9192func TestCancel_ReturnsErrorOnEmptySqid (t * testing.T ) {
9293 ctrl := gomock .NewController (t )
9394
94- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newRequestLogStoreNoop ( t , ctrl ) , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
95+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newCancelStorageFixture ( ctrl , "test-queue/42" ). storage , newCancelTestRegistryWithNoopPublisher (t , ctrl ))
9596 ctx := context .Background ()
9697
9798 req := & pb.CancelRequest {Sqid : "" , Reason : "anything" }
@@ -116,7 +117,7 @@ func TestCancel_PublishesToQueue(t *testing.T) {
116117 },
117118 )
118119
119- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newRequestLogStoreNoop ( t , ctrl ) , registry )
120+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newCancelStorageFixture ( ctrl , "my-queue/7" ). storage , registry )
120121 ctx := context .Background ()
121122
122123 req := & pb.CancelRequest {Sqid : "my-queue/7" , Reason : "obsolete change" }
@@ -133,91 +134,57 @@ func TestCancel_PublishesToQueue(t *testing.T) {
133134 assert .Equal (t , "obsolete change" , deserialized .Reason )
134135}
135136
136- // TestCancel_InsertsCancellingLog asserts that Cancel records a RequestStatusCancelling
137- // log entry (intent) carrying the reason in metadata, and that the entry is written
138- // before the cancel topic publish so observers see intent the moment Cancel returns.
139- func TestCancel_InsertsCancellingLog (t * testing.T ) {
137+ // TestCancel_MaterializesCancellingBeforePublish asserts that Cancel records the intent before publishing.
138+ func TestCancel_MaterializesCancellingBeforePublish (t * testing.T ) {
140139 ctrl := gomock .NewController (t )
141-
142- var insertedLog entity.RequestLog
143- logStore := storagemock .NewMockRequestLogStore (ctrl )
144- logStore .EXPECT ().List (gomock .Any (), "my-queue/42" ).Return ([]entity.RequestLog {{}}, nil )
145- logStore .EXPECT ().Insert (gomock .Any (), gomock .Any ()).DoAndReturn (
146- func (_ context.Context , entry entity.RequestLog ) error {
147- insertedLog = entry
148- return nil
149- },
150- ).Times (1 )
140+ fixture := newCancelStorageFixture (ctrl , "my-queue/42" )
151141
152142 registry , publisher := newCancelTestRegistry (t , ctrl )
153- insertedBeforePublish := false
154143 publisher .EXPECT ().Publish (gomock .Any (), gomock .Any (), gomock .Any ()).DoAndReturn (
155144 func (_ context.Context , _ string , _ entityqueue.Message ) error {
156- insertedBeforePublish = insertedLog .RequestID != ""
145+ summary , err := fixture .summaryStore .Get (context .Background (), "my-queue/42" )
146+ require .NoError (t , err )
147+ assert .Equal (t , entity .RequestStatusCancelling , summary .Status )
148+ assert .Equal (t , "obsolete change" , summary .Metadata ["reason" ])
157149 return nil
158150 },
159151 )
160152
161- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , logStore , registry )
162-
163- req := & pb.CancelRequest {Sqid : "my-queue/42" , Reason : "obsolete change" }
164- _ , err := controller .Cancel (context .Background (), req )
153+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , fixture .storage , registry )
154+ _ , err := controller .Cancel (context .Background (), & pb.CancelRequest {Sqid : "my-queue/42" , Reason : "obsolete change" })
165155 require .NoError (t , err )
166-
167- assert .Equal (t , "my-queue/42" , insertedLog .RequestID )
168- assert .Equal (t , entity .RequestStatusCancelling , insertedLog .Status )
169- assert .Equal (t , "obsolete change" , insertedLog .Metadata ["reason" ])
170- assert .True (t , insertedBeforePublish , "log entry must be inserted before publish to the cancel topic" )
171156}
172157
173- // TestCancel_LogInsertFailure asserts that a failure to insert the Cancelling log entry
174- // short-circuits the RPC with an error and the cancel topic is never published to.
175- func TestCancel_LogInsertFailure (t * testing.T ) {
158+ func TestCancel_LogInsertFailureSkipsPublish (t * testing.T ) {
176159 ctrl := gomock .NewController (t )
177-
178- logStore := storagemock .NewMockRequestLogStore (ctrl )
179- logStore .EXPECT ().List (gomock .Any (), "q/1" ).Return ([]entity.RequestLog {{}}, nil )
180- logStore .EXPECT ().Insert (gomock .Any (), gomock .Any ()).Return (fmt .Errorf ("db unavailable" ))
181-
160+ fixture := newCancelStorageFixture (ctrl , "q/1" )
161+ fixture .setLogInsertError (fmt .Errorf ("db unavailable" ))
182162 registry , publisher := newCancelTestRegistry (t , ctrl )
183- // No Publish expectation: log insert must fail before publish runs.
184163 _ = publisher
185164
186- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , logStore , registry )
165+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , fixture . storage , registry )
187166 _ , err := controller .Cancel (context .Background (), & pb.CancelRequest {Sqid : "q/1" })
188167 require .Error (t , err )
189168}
190169
191170func TestCancel_ReturnsErrorOnPublishFailure (t * testing.T ) {
192171 ctrl := gomock .NewController (t )
193-
172+ fixture := newCancelStorageFixture ( ctrl , "test-queue/1" )
194173 registry , publisher := newCancelTestRegistry (t , ctrl )
195174 publisher .EXPECT ().Publish (gomock .Any (), gomock .Any (), gomock .Any ()).Return (fmt .Errorf ("queue unavailable" ))
196175
197- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , newRequestLogStoreNoop (t , ctrl ), registry )
198- ctx := context .Background ()
199-
200- req := & pb.CancelRequest {Sqid : "test-queue/1" }
201- _ , err := controller .Cancel (ctx , req )
202-
176+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , fixture .storage , registry )
177+ _ , err := controller .Cancel (context .Background (), & pb.CancelRequest {Sqid : "test-queue/1" })
203178 require .Error (t , err )
204179}
205180
206- // TestCancel_UnknownSqidIsUserError asserts that Cancel for a sqid with no
207- // request_log history fails fast with a RequestNotFoundError (user error) and
208- // never inserts a cancelling log row or publishes to the cancel topic.
209181func TestCancel_UnknownSqidIsUserError (t * testing.T ) {
210182 ctrl := gomock .NewController (t )
211-
212- logStore := storagemock .NewMockRequestLogStore (ctrl )
213- logStore .EXPECT ().List (gomock .Any (), "ghost/1" ).Return (nil , storage .ErrNotFound )
214- // No Insert expectation: existence check must short-circuit before Insert.
215-
183+ fixture := newCancelStorageFixture (ctrl , "" )
216184 registry , publisher := newCancelTestRegistry (t , ctrl )
217- // No Publish expectation: existence check must short-circuit before Publish.
218185 _ = publisher
219186
220- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , logStore , registry )
187+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , fixture . storage , registry )
221188 _ , err := controller .Cancel (context .Background (), & pb.CancelRequest {Sqid : "ghost/1" })
222189 require .Error (t , err )
223190 assert .True (t , IsRequestNotFound (err ))
@@ -229,19 +196,19 @@ func TestCancel_UnknownSqidIsUserError(t *testing.T) {
229196 assert .Equal (t , "ghost/1" , typed .Sqid )
230197}
231198
232- // TestCancel_RequestLogLookupFailure asserts that an infrastructure failure on
233- // the existence check propagates as a (non-user) error and skips the rest of
234- // the pipeline.
235- func TestCancel_RequestLogLookupFailure (t * testing.T ) {
199+ func TestCancel_RequestSummaryLookupFailure (t * testing.T ) {
236200 ctrl := gomock .NewController (t )
237-
238- logStore := storagemock .NewMockRequestLogStore (ctrl )
239- logStore .EXPECT ().List (gomock .Any (), "q/1" ).Return (nil , fmt .Errorf ("log backend down" ))
240-
201+ store := storagemock .NewMockStorage (ctrl )
202+ summaryStore := storagemock .NewMockRequestSummaryStore (ctrl )
203+ store .EXPECT ().GetRequestSummaryStore ().Return (summaryStore ).AnyTimes ()
204+ store .EXPECT ().GetRequestLogStore ().Return (storagemock .NewMockRequestLogStore (ctrl )).AnyTimes ()
205+ store .EXPECT ().GetRequestQueueSummaryStore ().Return (storagemock .NewMockRequestQueueSummaryStore (ctrl )).AnyTimes ()
206+ store .EXPECT ().GetRequestURIStore ().Return (storagemock .NewMockRequestURIStore (ctrl )).AnyTimes ()
207+ summaryStore .EXPECT ().Get (gomock .Any (), "q/1" ).Return (entity.RequestSummary {}, fmt .Errorf ("summary backend down" ))
241208 registry , publisher := newCancelTestRegistry (t , ctrl )
242209 _ = publisher
243210
244- controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , logStore , registry )
211+ controller := NewCancelController (zap .NewNop ().Sugar (), tally .NoopScope , store , registry )
245212 _ , err := controller .Cancel (context .Background (), & pb.CancelRequest {Sqid : "q/1" })
246213 require .Error (t , err )
247214 assert .False (t , errs .IsUserError (err ))
0 commit comments