getConfigVersionWithRetry attempts to retrieve the specified config file. On file not found, will perform backoff retry up to specified timeout. On timeout, returns the nil and rollback error. On mismatched version when registry version is newer, will perform backoff retry up to timeout. On timeou
(ctx context.Context, bucketName, groupID, dbName, version string)
| 425 | // On mismatched version when registry version is newer, will perform backoff retry up to timeout. On timeout, returns the config and rollback error. |
| 426 | // On mismatched version when config version is newer, returns the config and ErrConfigVersionMismatch. |
| 427 | func (b *bootstrapContext) getConfigVersionWithRetry(ctx context.Context, bucketName, groupID, dbName, version string) (*DatabaseConfig, error) { |
| 428 | |
| 429 | timeout := defaultConfigRetryTimeout |
| 430 | if b.configRetryTimeout != 0 { |
| 431 | timeout = b.configRetryTimeout |
| 432 | } |
| 433 | |
| 434 | retryWorker := func() (shouldRetry bool, err error, value interface{}) { |
| 435 | config := &DatabaseConfig{} |
| 436 | metadataKey := PersistentConfigKey(ctx, groupID, dbName) |
| 437 | cas, err := b.Connection.GetMetadataDocument(ctx, bucketName, metadataKey, config) |
| 438 | if base.IsDocNotFoundError(err) { |
| 439 | return true, base.ErrConfigRegistryRollback, nil |
| 440 | } |
| 441 | if err != nil { |
| 442 | return false, err, nil |
| 443 | } |
| 444 | |
| 445 | config.cfgCas = cas |
| 446 | |
| 447 | if version == invalidDatabaseConflictingCollectionsVersion { |
| 448 | // special case - return the invalid config to use in updates (repairs). Configs with this version will not be loaded by SG. |
| 449 | config.Version = invalidDatabaseConflictingCollectionsVersion |
| 450 | return false, nil, config |
| 451 | } |
| 452 | |
| 453 | // If version matches, success! |
| 454 | if config.Version == version { |
| 455 | return false, nil, config |
| 456 | } |
| 457 | |
| 458 | // For version mismatch, handling depends on whether config has newer or older version than requested |
| 459 | requestedGen, _ := db.ParseRevID(ctx, version) |
| 460 | currentGen, _ := db.ParseRevID(ctx, config.Version) |
| 461 | if currentGen > requestedGen { |
| 462 | // If the config has a newer version than requested, return the config but alert caller that they have |
| 463 | // requested a stale version. |
| 464 | return false, base.ErrConfigVersionMismatch, config |
| 465 | } |
| 466 | |
| 467 | base.InfofCtx(ctx, base.KeyConfig, "getConfigVersionWithRetry for key %s found version mismatch, retrying. Requested: %s, Found: %s", metadataKey, version, config.Version) |
| 468 | return true, base.ErrConfigRegistryRollback, config |
| 469 | } |
| 470 | |
| 471 | // Kick off the retry loop |
| 472 | err, retryResult := base.RetryLoop( |
| 473 | ctx, |
| 474 | "Wait for config version match", |
| 475 | retryWorker, |
| 476 | base.CreateDoublingSleeperDurationFunc(50, timeout), |
| 477 | ) |
| 478 | |
| 479 | // Return the config with rollback error, to support rollback by the caller if appropriate |
| 480 | if err != nil && err != base.ErrConfigRegistryRollback { |
| 481 | return nil, err |
| 482 | } |
| 483 | |
| 484 | if retryResult != nil { |
no test coverage detected