Repository navigation
test(bigtable): fix flaky backup system tests - #9717
danieljbruce wants to merge 7 commits into
Conversation
There was a problem hiding this comment.
Code Review
This pull request introduces a withBackupQuotaRetry helper function to handle RESOURCE_EXHAUSTED quota errors during Bigtable backup operations in system tests, wrapping various backup creation, copy, and deletion calls. It also refactors test setup and teardown to improve resource cleanup and dynamic ID generation. The review feedback suggests removing an unconditional 60-second sleep in a before hook to speed up successful test runs, utilizing non-nullable local constants (createdBackup and copiedBackup) to avoid non-null assertions and potential TypeScript strict null check issues, and using an inline structural type assertion for error code checks to prevent potential import issues.
| // Sleep here for just over a minute before the "before all" hook creates | ||
| // backups so that requests from the preceding backup tests do not trigger | ||
| // per-minute 'Backup metadata write requests' quota exhaustion. | ||
| await new Promise(r => setTimeout(r, 60001)); | ||
| const [backupOpSSD] = await withBackupQuotaRetry(() => |
There was a problem hiding this comment.
Unconditional 60-second sleep in the before hook adds a significant delay to the test suite on every run, even when there is no quota exhaustion. Since both createBackup calls inside this hook are already wrapped in withBackupQuotaRetry, any quota exhaustion will be handled dynamically and retried with a delay only when necessary. Removing this unconditional sleep will speed up successful test runs by a full minute.
const [backupOpSSD] = await withBackupQuotaRetry(() =>| const [copiedBackup, copyOperation] = await withBackupQuotaRetry(() => | ||
| backup!.copy(config), | ||
| ); |
There was a problem hiding this comment.
Using createdBackup directly instead of backup! is safer and avoids the need for a non-null assertion operator (!), as createdBackup is a non-nullable constant in this scope.
| const [copiedBackup, copyOperation] = await withBackupQuotaRetry(() => | |
| backup!.copy(config), | |
| ); | |
| const [copiedBackup, copyOperation] = await withBackupQuotaRetry(() => | |
| createdBackup.copy(config), | |
| ); |
| // Restore a table from the copied backup | ||
| const [newTable, restoreOperation] = | ||
| await newBackup.restore('new-table'); | ||
| const [restoredTable, restoreOperation] = | ||
| await newBackup.restore(restoredTableId); |
There was a problem hiding this comment.
Using copiedBackup directly instead of newBackup avoids potential TypeScript compilation errors under strictNullChecks, as newBackup is declared as Backup | undefined and is not asserted or narrowed here.
| // Restore a table from the copied backup | |
| const [newTable, restoreOperation] = | |
| await newBackup.restore('new-table'); | |
| const [restoredTable, restoreOperation] = | |
| await newBackup.restore(restoredTableId); | |
| // Restore a table from the copied backup | |
| const [restoredTable, restoreOperation] = | |
| await copiedBackup.restore(restoredTableId); |
| const isQuotaError = | ||
| (err as ServiceError)?.code === 8 || | ||
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); |
There was a problem hiding this comment.
To avoid potential TypeScript compilation errors if ServiceError is not imported in this file, you can use an inline structural type assertion (err as {code?: number}) instead of (err as ServiceError).
| const isQuotaError = | |
| (err as ServiceError)?.code === 8 || | |
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); | |
| const isQuotaError = | |
| (err as {code?: number})?.code === 8 || | |
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); |
… style guidelines
|
/gemini review |
There was a problem hiding this comment.
Code Review
This pull request enhances the reliability of Bigtable system tests by wrapping backup operations in a new withBackupQuotaRetry helper function, which retries operations upon encountering RESOURCE_EXHAUSTED quota errors. Additionally, it improves test isolation and resource cleanup by scoping variables locally and utilizing try...finally blocks to delete created backups, tables, and instances. The review feedback recommends replacing the ServiceError type cast with a structural type cast to prevent potential TypeScript compilation errors if ServiceError is not imported.
| const isQuotaError = | ||
| (err as ServiceError)?.code === 8 || | ||
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); |
There was a problem hiding this comment.
Using ServiceError without an explicit import from @grpc/grpc-js or google-gax can lead to TypeScript compilation errors if the type is not already in scope. To ensure robust compilation and avoid unnecessary imports in the test file, consider using a structural type cast like (err as {code?: number}) or (err as any).
| const isQuotaError = | |
| (err as ServiceError)?.code === 8 || | |
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); | |
| const isQuotaError = | |
| (err as {code?: number})?.code === 8 || | |
| (err as Error)?.message?.includes('RESOURCE_EXHAUSTED'); |
…n backup system test
|
[Generated] Fixed the CI issues on this PR in commit
|
…-side metrics export interval
|
[Generated] Addressed the remaining CI failures on this PR (
|
| if (endNanos >= 1_000_000_000) { | ||
| endSec += 1; | ||
| endNanos -= 1_000_000_000; | ||
| } |
There was a problem hiding this comment.
Modifying the timestamps for our metrics does not seem like something we should do.
Description
This change fixes flaky backup system tests in the Bigtable package.
Impact
It prevents table collisions and backup metadata write quota failures during CI.
Changes
'old-table'and'new-table'identifiers inshould restore a copied backupwithgenerateId('table'), wait for table replication before creating the source backup, and delete both created tables and backups infinallyso Mocha test retries (--retries 3) do not fail with6 ALREADY_EXISTS: Table already exists.destinationClusterId) inshould create backup of a table and copy it on another cluster of the same instance(and move secondary instance deletion intofinallyblocks) so extra clusters do not leak into subsequent tests on the shared instance.beforehook inbackups with gapic(since Mocha runsbeforehooks prior tobeforeEachhooks and does not retrybeforehooks) and retry backup metadata write operations on8 RESOURCE_EXHAUSTEDquota errors.Testing
handwritten/bigtableand verified existing unit tests and strict linter checks pass.backupsandbackups with gapicsystem test setup and teardown paths inhandwritten/bigtable/system-test/bigtable.ts.Alternatives
should restore a copied backupandbackups with gapicvulnerable toALREADY_EXISTStable collisions on Mocha retries andRESOURCE_EXHAUSTEDbackup metadata write quota failures in CI.beforeEachdelays without a cooldown inbackups with gapic'sbeforehook or unique table IDs does not protect thebeforehook or retry attempts.