@@ -187,14 +187,16 @@ var _ = Describe("Runner", func() {
187187
188188 Context ("with task runner and context" , func () {
189189 var taskRunner * dexcomFetch.TaskRunner
190+ var logger * logTest.Logger
190191 var ctx context.Context
191192
192193 BeforeEach (func () {
193194 var err error
194195 taskRunner , err = dexcomFetch .NewTaskRunner (provider , tsk )
195196 Expect (err ).ToNot (HaveOccurred ())
196197 Expect (taskRunner ).ToNot (BeNil ())
197- ctx = log .NewContextWithLogger (context .Background (), logTest .NewLogger ())
198+ logger = logTest .NewLogger ()
199+ ctx = log .NewContextWithLogger (context .Background (), logger )
198200 })
199201
200202 assertTaskState := func (state string ) {
@@ -364,6 +366,21 @@ var _ = Describe("Runner", func() {
364366 assertTaskAndDataSourceError (dexcomFetch .ErrorCodeResourceFailure , "unable to get provider session" )
365367 })
366368
369+ It ("discards the run outcome if the task claim is lost" , func () {
370+ claimContext , claimCancel := context .WithCancelCause (ctx )
371+ defer claimCancel (nil )
372+ testErr := errorsTest .RandomError ()
373+ authClient .EXPECT ().GetProviderSession (matchContext (), "test-provider-session-id" ).DoAndReturn (func (ctx context.Context , id string ) (* auth.ProviderSession , error ) {
374+ claimCancel (task .ErrClaimLost )
375+ return nil , testErr
376+ })
377+ taskRunner .Run (claimContext )
378+ assertTaskState (task .TaskStateRunning )
379+ Expect (dataSrc .State ).To (Equal (dataSource .StateConnected ))
380+ Expect (dataSrc .HasError ()).To (BeFalse ())
381+ logger .AssertWarn ("Skipped updating data source and task because the task claim was lost" )
382+ })
383+
367384 It ("fails if the provider session is missing" , func () {
368385 authClient .EXPECT ().GetProviderSession (matchContext (), "test-provider-session-id" ).Return (nil , nil )
369386 dataSourceClient .EXPECT ().Update (matchContext (), "test-data-source-id" , matchNil (), matchNotNil ()).DoAndReturn (mockDataSourceClientUpdate (dataSrc ))
@@ -643,7 +660,78 @@ var _ = Describe("Runner", func() {
643660 // deviceHashes - not in data
644661 // dataSource.LatestDataTime - not nil (recent)
645662 // refresh token
646- // data ranges multiple 30 day segments
663+ })
664+
665+ Context ("with provider session and a data range spanning multiple chunks" , func () {
666+ var providerSession * auth.ProviderSession
667+ var firstChunkStartTime time.Time
668+ var firstChunkEndTime time.Time
669+ var secondChunkEndTime time.Time
670+
671+ BeforeEach (func () {
672+ providerSession = & auth.ProviderSession {
673+ ID : "test-provider-session-id" ,
674+ UserID : "test-user-id" ,
675+ OAuthToken : & auth.OAuthToken {
676+ AccessToken : "test-access-token-1" ,
677+ TokenType : "Bearer" ,
678+ RefreshToken : "test-refresh-token-1" ,
679+ ExpirationTime : time .Now ().Add (time .Minute ),
680+ },
681+ }
682+ authClient .EXPECT ().GetProviderSession (matchContext (), "test-provider-session-id" ).Return (providerSession , nil )
683+ authClient .EXPECT ().UpdateProviderSession (matchContext (), "test-provider-session-id" , matchNotNil ()).DoAndReturn (mockAuthClientUpdateProviderSession (providerSession )).AnyTimes ()
684+ firstChunkStartTime = time .Now ().Add (- 45 * Day )
685+ firstChunkEndTime = firstChunkStartTime .AddDate (0 , 0 , dexcomFetch .DataRangeDaysMaximum )
686+ secondChunkEndTime = time .Now ().Add (- 3 * Day )
687+ dataRangeResponse := & dexcom.DataRangesResponse {
688+ Calibrations : & dexcom.DataRange {
689+ Start : & dexcom.Moment {SystemTime : & dexcom.Time {Time : firstChunkStartTime }},
690+ End : & dexcom.Moment {SystemTime : & dexcom.Time {Time : secondChunkEndTime }},
691+ },
692+ }
693+ dexcomClient .EXPECT ().GetDataRange (matchContext (), nil , matchNotNil ()).DoAndReturn (mockDexcomClientGetDataRange (nil , dataRangeResponse , nil ))
694+ })
695+
696+ // Expects the fetch of a single chunk, all responses empty, invoking onEvents, if any, during the
697+ // final fetch of the chunk
698+ expectFetchChunk := func (startTime time.Time , endTime time.Time , onEvents func ()) {
699+ dexcomClient .EXPECT ().GetAlerts (matchContext (), startTime , endTime , matchNotNil ()).DoAndReturn (mockDexcomClientGetData (nil , & dexcom.AlertsResponse {Records : & dexcom.Alerts {}}, nil ))
700+ dexcomClient .EXPECT ().GetCalibrations (matchContext (), startTime , endTime , matchNotNil ()).DoAndReturn (mockDexcomClientGetData (nil , & dexcom.CalibrationsResponse {Records : & dexcom.Calibrations {}}, nil ))
701+ dexcomClient .EXPECT ().GetDevices (matchContext (), startTime , endTime , matchNotNil ()).DoAndReturn (mockDexcomClientGetData (nil , & dexcom.DevicesResponse {Records : & dexcom.Devices {}}, nil ))
702+ dexcomClient .EXPECT ().GetEGVs (matchContext (), startTime , endTime , matchNotNil ()).DoAndReturn (mockDexcomClientGetData (nil , & dexcom.EGVsResponse {Records : & dexcom.EGVs {}}, nil ))
703+ dexcomClient .EXPECT ().GetEvents (matchContext (), startTime , endTime , matchNotNil ()).DoAndReturn (func (ctx context.Context , startTime time.Time , endTime time.Time , tokenSource oauth.TokenSource ) (* dexcom.EventsResponse , error ) {
704+ if onEvents != nil {
705+ onEvents ()
706+ }
707+ return & dexcom.EventsResponse {Records : & dexcom.Events {}}, nil
708+ })
709+ }
710+
711+ It ("fetches every chunk of the data range" , func () {
712+ expectFetchChunk (firstChunkStartTime , firstChunkEndTime , nil )
713+ expectFetchChunk (firstChunkEndTime , secondChunkEndTime , nil )
714+ dataSourceClient .EXPECT ().Update (matchContext (), "test-data-source-id" , matchNil (), matchNotNil ()).DoAndReturn (mockDataSourceClientUpdate (dataSrc ))
715+ taskRunner .Run (ctx )
716+ assertTaskAndDataSourceState (task .TaskStatePending )
717+ assertTaskAvailableAfterStandardDuration ()
718+ assertTaskRetryCountNotPresent ()
719+ assertTaskAndDataSourceErrorNotPresent ()
720+ assertDataSourceLastImportTimePresent ()
721+ })
722+
723+ It ("discards the run outcome if the task claim is lost mid-fetch" , func () {
724+ claimContext , claimCancel := context .WithCancelCause (ctx )
725+ defer claimCancel (nil )
726+ expectFetchChunk (firstChunkStartTime , firstChunkEndTime , func () { claimCancel (task .ErrClaimLost ) })
727+ // The canceled context fails the next chunk, ending the run
728+ dexcomClient .EXPECT ().GetAlerts (matchContext (), firstChunkEndTime , secondChunkEndTime , matchNotNil ()).DoAndReturn (mockDexcomClientGetData [dexcom.AlertsResponse ](nil , nil , context .Canceled ))
729+ taskRunner .Run (claimContext )
730+ assertTaskState (task .TaskStateRunning )
731+ Expect (dataSrc .State ).To (Equal (dataSource .StateConnected ))
732+ Expect (dataSrc .HasError ()).To (BeFalse ())
733+ logger .AssertWarn ("Skipped updating data source and task because the task claim was lost" )
734+ })
647735 })
648736 })
649737 })
0 commit comments