Verify that a continuous changes feed hitting an error when building its late sequence feed will roll back to its low sequence value, then recover and successfully send subsequent late sequences.
(t *testing.T)
| 229 | // Verify that a continuous changes feed hitting an error when building its late sequence feed will roll back to |
| 230 | // its low sequence value, then recover and successfully send subsequent late sequences. |
| 231 | func TestLateSequenceErrorRecovery(t *testing.T) { |
| 232 | |
| 233 | base.SetUpTestLogging(t, base.LevelTrace, base.KeyChanges, base.KeyCache) |
| 234 | |
| 235 | db, ctx := setupTestDBWithCacheOptions(t, shortWaitCache()) |
| 236 | defer db.Close(ctx) |
| 237 | |
| 238 | // Create a user with access to channel ABC |
| 239 | authenticator := db.Authenticator(ctx) |
| 240 | require.NotNil(t, authenticator, "db.Authenticator(db.Ctx) returned nil") |
| 241 | user, err := authenticator.NewUser("naomi", "letmein", channels.BaseSetOf(t, "ABC")) |
| 242 | require.NoError(t, err, "Error creating new user") |
| 243 | require.NoError(t, authenticator.Save(user)) |
| 244 | |
| 245 | dbCollection, ctx := GetSingleDatabaseCollectionWithUser(ctx, t, db) |
| 246 | |
| 247 | // Start continuous changes feed |
| 248 | var options ChangesOptions |
| 249 | options.Since = SequenceID{Seq: 0} |
| 250 | ctx, changesCtxCancel := context.WithCancel(ctx) |
| 251 | options.ChangesCtx = ctx |
| 252 | defer changesCtxCancel() |
| 253 | options.Continuous = true |
| 254 | options.Wait = true |
| 255 | feed, err := dbCollection.MultiChangesFeed(ctx, base.SetOf("ABC"), options) |
| 256 | require.NoError(t, err, "Feed initialization error") |
| 257 | |
| 258 | // Reads events until it gets a nil event, which indicates the changes loop has entered wait mode. |
| 259 | // Returns slice of non-nil events received. |
| 260 | nextFeedIteration := func() []*ChangeEntry { |
| 261 | events := make([]*ChangeEntry, 0) |
| 262 | for { |
| 263 | select { |
| 264 | case event := <-feed: |
| 265 | if event == nil { |
| 266 | return events |
| 267 | } |
| 268 | events = append(events, event) |
| 269 | case <-time.After(10 * time.Second): |
| 270 | assert.Fail(t, "Expected sequence didn't arrive over feed") |
| 271 | return nil |
| 272 | } |
| 273 | } |
| 274 | } |
| 275 | |
| 276 | nextEvents := nextFeedIteration() |
| 277 | assert.Equal(t, len(nextEvents), 0) // Empty feed indicates changes is in wait mode |
| 278 | |
| 279 | collection := dbCollection.DatabaseCollection |
| 280 | // Write sequence 1, wait for it on feed |
| 281 | WriteDirect(t, collection, []string{"ABC"}, 1) |
| 282 | |
| 283 | nextEvents = nextFeedIteration() |
| 284 | require.Equal(t, len(nextEvents), 1) |
| 285 | assert.Equal(t, nextEvents[0].Seq.String(), "1") |
| 286 | |
| 287 | // Write sequence 6, wait for it on feed |
| 288 | WriteDirect(t, collection, []string{"ABC"}, 6) |
nothing calls this directly
no test coverage detected