Skip to content

[Collections] CLI 'remove' results in "database is locked" error #3225

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 3 commits into from
Jan 27, 2021

Conversation

yim-lee
Copy link
Contributor

@yim-lee yim-lee commented Jan 26, 2021

Motivation:
Using the package-collection CLI, the remove command results in "database is locked" error even though the collection is removed successfully. This is because a SQLitePackageCollectionsStorage is created at the beginning of each command run, and in the initializer the time-consuming populateTargetTrie is called. When the command finishes running, it triggers SQLitePackageCollectionsStorage to be closed, which in turn closes the SQLite connection, but this is done while populateTargetTrie is still running and thus causes the "database is locked" error.

Modifications:

  • Initializing PackageCollections can be expensive and should only be done once in a command
  • Add and set isShuttingDown flag when SQLitePackageCollectionsStorage.close is called so populateTargetTrie knows that it should stop.
  • Try db.close in a second attempt after allowing time for database operations to react to isShuttingDown flag
  • populateTargetTrie should memoize its result

Result:
No "database is locked" error.

Motivation:
Using the `package-collection` CLI, the `remove` command results in "database is locked" error even though the collection is removed successfully. This is because a `SQLitePackageCollectionsStorage` is created at the beginning of each command run, and in the initializer the time-consuming `populateTargetTrie` is called. When the command finishes running, it triggers `SQLitePackageCollectionsStorage` to be closed, which in turn closes the SQLite connection, but this is done while `populateTargetTrie` is still running and thus causes the "database is locked" error.

Modifications:
- Initializing `PackageCollections` can be expensive and should only be done once in a command
- Add and set `isShuttingDown` flag when `SQLitePackageCollectionsStorage.close` is called so `populateTargetTrie` knows that it should stop.
- Try `db.close` in a second attempt after allowing time for database operations to react to `isShuttingDown` flag
- `populateTargetTrie` should memoize its result

Result:
No "database is locked" error.
@yim-lee
Copy link
Contributor Author

yim-lee commented Jan 26, 2021

@swift-ci please smoke test

guard case .success = semaphore.wait(timeout: .now() + .milliseconds(300)) else {
throw StringError("Failed to close database")
}
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

in general the approach seems fine, but the delay here could be fragile - if the DB operation is longer than 200/300ms it will still fail with "db is locked", we could potentially do a recursive "exponential backoff" style thing here which would be safer. alternatively we could try to eliminate the issue using "sqlite3_interrupt" before trying to close again

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Exponential backoff: 0a70a65

@yim-lee
Copy link
Contributor Author

yim-lee commented Jan 27, 2021

@swift-ci please smoke test

@yim-lee
Copy link
Contributor Author

yim-lee commented Jan 27, 2021

@swift-ci please smoke test

@yim-lee yim-lee merged commit 265c1ed into swiftlang:main Jan 27, 2021
@yim-lee yim-lee deleted the db-locked-1 branch January 27, 2021 22:32
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants