Skip to content
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

Fix Sqlite database locking issue #13246

Merged
merged 5 commits into from
Oct 24, 2022

Conversation

Zeegaan
Copy link
Member

@Zeegaan Zeegaan commented Oct 20, 2022

Issue

  • When saving 2 document types (with templates) at the same time, the SqlLite database would totally lock up, and thus the whole application would be unusable.
    This happens because when we save a document type, it needs to also create a template file on disk, thus it calls the FileService CreateTemplateForContentType, this file service would create a scope, get a read & write lock, and then call the TemplateRepository, that then would insert the template both in the database, but also create the file on disk.
    All while the other thread would do the exact same steps as above, which would then result in the complete locking of the database. Why this results in the complete locking of the database I'm not sure, but it seems like both are taking writelocks, locking the database, but now its locked so neither can write.

Here is me replicating the issue:
SqliteFreeze

Notes

  • I have implemented a lock, that prevents simultaneous creation of these scopes in the FileService, which prevents the issue.
  • This could also be solved by changing the IsolationLevel for the scope, so it would be using ICoreScope scope = ScopeProvider.CreateCoreScope(IsolationLevel.UnCommited); but this changed how strictly the database handles locking.

How to test

  • Run a fresh umbraco install in debug
  • Set a breakpoint in ContentTypeController in the PostSave action on line 319.
    image
  • Open backoffice in 2 tabs and create a document type in each (do not press save yet)
  • When both is ready, save the first (it should hit the breakpoint), when the breakpoint is hit, save the other.
  • Now both should be caught on the breakpoint which ensures they will run simultaneously.
  • Remove the breakpoint and run the application (F5), this should no longer result in the locking of the database, and thus both document types should be saved 👍

@ronaldbarendse
Copy link
Contributor

@Zeegaan This is probably only an issue in SQLite because that allows at most one writer to proceed concurrently . Both FileService and ContentTypeService will create separate write transactions, but the parent transaction is only committed at the end of the request, causing them to deadlock. A better solution might be to create a single scope that wraps both service calls, so there's only a single scope that takes a write lock...

@Zeegaan
Copy link
Member Author

Zeegaan commented Oct 21, 2022

As @ronaldbarendse mentioned there is even more solutions to this problem, this will need an internal discussion before getting merged 👍

@matthewcare
Copy link
Contributor

@Zeegaan
I found this issue when implementing batch media uploads (#12947)
I added Semaphore to the API to only process on a single thread at a time, effectively queuing the requests.
Still waiting back from HQ about if that's the preferred method, but it seems like whatever the answer is is how this should also be handled?

@Zeegaan
Copy link
Member Author

Zeegaan commented Oct 22, 2022

@matthewcare We will have a discussion monday on how to go about it, but I agree, we should probably handle both the same way, thanks for letting me know! 🙌

@Zeegaan Zeegaan merged commit 73bbff0 into v10/dev Oct 24, 2022
@Zeegaan Zeegaan deleted the v10/bugfix/fix-fileservice-race-condition branch October 24, 2022 11:45
nikolajlauridsen pushed a commit that referenced this pull request Oct 26, 2022
* Add locking for creating scope

* Lock the repository instead

* Add scope in action instead of locking in service

* Fix up post-merge

Co-authored-by: Zeegaan <nge@umbraco.dk>
@ronaldbarendse
Copy link
Contributor

This must be one of the deadlock issues mentioned in dotnet/efcore#28172 (comment), as Umbraco opts-in to this 'pit-of-failure' 🤔

Zeegaan added a commit that referenced this pull request Nov 8, 2022
* Bump version

* Add IContextCache to deploy connectors (#13287)

* Add IContextCache and implementations

* Update connector interfaces to use IContextCache

* Minor cleanup

* Move DeployContextCache prefix to constant

* Move default implementations to obsolete methods

* Remove DeployContextCache and DictionaryCache

Co-authored-by: Andy Butland <abutland73@gmail.com>

* Add IContextCache to deploy connectors (#13287)

* Add IContextCache and implementations

* Update connector interfaces to use IContextCache

* Minor cleanup

* Move DeployContextCache prefix to constant

* Move default implementations to obsolete methods

* Remove DeployContextCache and DictionaryCache

Co-authored-by: Andy Butland <abutland73@gmail.com>

* Parse lockId as invariant (#13284)

Co-authored-by: Zeegaan <nge@umbraco.dk>

* Fix Sqlite database locking issue (#13246)

* Add locking for creating scope

* Lock the repository instead

* Add scope in action instead of locking in service

* Fix up post-merge

Co-authored-by: Zeegaan <nge@umbraco.dk>

* Bump version to next minor

* Fix for UseExceptionHandler no longer working since v10.3 RC (#13218)

* Fix for UseExceptionHandler no longer working since v10.3 RC

* Update the management api path to match the new one

Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>

* New backoffice: Cleanup management API routes (#13296)

* Rename ModelsBuilderDashboard folder to ModelsBuilder

* Fix modelsbuilder paths and related naming

* Rename analytics route to telemetry

* Fix controller bases - routes and tags

* Fix items route

* Fix more controllerbase routes

* Fix route

* Fix OpenApi file

* Merging DictionaryItem and Dictionary

* Fix TrackedReferences naming

* Update OpenApi file

* Rename Analytics* related types to Telemetry*

* New Backoffice: Return AnalyticsLevelViewModel from Telemetry/ (#13298)

* Return TelemetryLevelViewModel instead of TelemetryLevel

* Fix schema

* Change telemetry/current to telemetry/level

(cherry picked from commit f2b8494)

* Add contants for tree and recycle-bin subpaths

(cherry picked from commit 4449f56)

Co-authored-by: Mole <nikolajlauridsen@protonmail.ch>

* Updated Smidge, Npoco and MailKit (#13310)

* Updated Smidge, Npoco and MailKit

* Added missing command (after breaking interface in npoco)

* OpenId Connect authentication for new management API (#13318)

* First attempt at OpenIddict

* Making headway and more TODOs

* Redo current policies for multiple schemas + clean up auth controller

* Fix bad merge

* Clean up some more test code

* Fix spacing

* Include AddAuthentication() in OpenIddict addition

* A little more clean-up

* Move application creation to its own implementation + prepare for middleware to handle valid callback URL

* Enable refresh token flow

* Fix bad merge from v11/dev

* Support auth for Swagger and Postman in non-production environments + use default login screen for back-office logins

* Add workaround to client side login handling so the OAuth return URL is not corrupted before redirection

* Add temporary configuration handling for new backoffice

* Restructure the code somewhat, move singular responsibility from management API project

* Add recurring task for cleaning up old tokens in the DB

* Fix bad merge + make auth controller align with the new management API structure

* Explicitly handle the new management API path as a backoffice path (NOTE: this is potentially behaviorally breaking!)

* Redo handle the new management API requests as backoffice requests, this time in a non-breaking way

* Add/update TODOs

* Revert duplication of current auth policies for OpenIddict (as it breaks everything for V11 without the new management APIs) and introduce a dedicated PoC policy setup for OpenIddict.

* Fix failing unit tests

* Update src/Umbraco.Cms.ManagementApi/Security/BackOfficeApplicationManager.cs

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* Update src/Umbraco.Cms.ManagementApi/Security/BackOfficeApplicationManager.cs

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* Update src/Umbraco.Cms.ManagementApi/Security/BackOfficeApplicationManager.cs

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* Update src/Umbraco.Core/Routing/UmbracoRequestPaths.cs

Co-authored-by: Nikolaj Geisle <70372949+Zeegaan@users.noreply.github.com>

* V11: Using IFileProvider to access assets added from packages (#13141)

* Creating a FileProviderFactory for getting the package.manifest and grid.editors.config.js files through a file provider

* Collecting the package.manifest-s from different sources

* Searching different sources for grid.editors.config.js

* Using an IFileProvider to collect all tours

* Refactoring IconService.cs

* Typo

* Optimizations when looping through the file system

* Moving WebRootFileProviderFactory to Umbraco.Web.Common proj

* Removes double registering

* pluginLangFileSources includes the localPluginFileSources

* Comments

* Remove linq from foreach

* Change workflow for grid.editors.config.js so we check first physical file, then RCL, then Embedded

* Clean up

* Check if config dir exists

* Discover nested package.manifest files

* Fix IFileInfo.PhysicalPath check

* Revert 712810e as that way files in content root are preferred over those in web root

* Adding comments

* Refactoring

* Remove PhysicalPath check

* Fix registration of WebRootFileProviderFactory

* Use Swashbuckle instead of NSwag (#13350)

* First attempt at OpenIddict

* Making headway and more TODOs

* Redo current policies for multiple schemas + clean up auth controller

* Fix bad merge

* Clean up some more test code

* Fix spacing

* Include AddAuthentication() in OpenIddict addition

* A little more clean-up

* Move application creation to its own implementation + prepare for middleware to handle valid callback URL

* Enable refresh token flow

* Fix bad merge from v11/dev

* Support auth for Swagger and Postman in non-production environments + use default login screen for back-office logins

* Add workaround to client side login handling so the OAuth return URL is not corrupted before redirection

* Add temporary configuration handling for new backoffice

* Restructure the code somewhat, move singular responsibility from management API project

* Add recurring task for cleaning up old tokens in the DB

* Fix bad merge + make auth controller align with the new management API structure

* Explicitly handle the new management API path as a backoffice path (NOTE: this is potentially behaviorally breaking!)

* Redo handle the new management API requests as backoffice requests, this time in a non-breaking way

* Add/update TODOs

* Replace NSwag with Swashbuckle and clean up unnecessary client secret workaround

* Revert duplication of current auth policies for OpenIddict (as it breaks everything for V11 without the new management APIs) and introduce a dedicated PoC policy setup for OpenIddict.

* Fix failing unit tests

* A little niceness + export new OpenApi.json and fix path in contract unit test

* Redo after merge with v11/dev + filter out unwanted mime types

* Remove CreatedResult and NotFoundObjectResult where possible

* Custom schema IDs - no more "ViewModel" postfix and make generic lists look less clunky too

* A little more explanation for generic schema ID generation

* Force Swashbuckle to use enum string names

* Update OpenApi.json to match new enum string values

* Add clarifying comment about weird looking construct

* add workflow to schema (#13349)

* add workflow to schema

* add licenses to CMSDefinition - intentionally only adding to schema, not registered as options

Co-authored-by: Nikolaj <nikolajlauridsen@protonmail.ch>
Co-authored-by: Ronald Barendse <ronald@barend.se>
Co-authored-by: Andy Butland <abutland73@gmail.com>
Co-authored-by: Zeegaan <nge@umbraco.dk>
Co-authored-by: Justin Neville <67802060+justin-nevitech@users.noreply.github.com>
Co-authored-by: Elitsa Marinovska <21998037+elit0451@users.noreply.github.com>
Co-authored-by: Bjarke Berg <mail@bergmania.dk>
Co-authored-by: Kenn Jacobsen <kja@umbraco.dk>
Co-authored-by: Nathan Woulfe <nathan@nathanw.com.au>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

5 participants