[WIP] [PoC] '&' -> '&mut' #777
No reviewers
Labels
No labels
A: API
A: Backend
A: Federation
A: Front-End
A: I18N
A: Meta
A: Security
Build
C: Bug
C: Discussion
C: Enhancement
C: Feature
Compatibility
Dependency
Design
Documentation
Good first issue
Help welcome
Mobile
Rendering
S: Blocked
S: Duplicate
S: Incomplete
S: Instance specific
S: Invalid
S: Needs Voting/Discussion
S: Ready for review
Suggestion
S: Voted on Loomio
S: Wontfix
No milestone
No project
No assignees
2 participants
Notifications
Due date
No due date set.
Dependencies
No dependencies set.
Reference: Plume/Plume#777
Loading…
Add table
Reference in a new issue
No description provided.
Delete branch "igalic/go/async-all-mut"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This is a (incomplete) proof of concept of a possible workaround for
Syncissues that appear inasynccode.Roughly, the issue is this:
Send. This requirement comes from Rocket, and would be nontrivial and/or undesirable to change in Rocket.&PlumeRocketor an&Connectionheld across anawaitpoint&PlumeRocket/&Connectionmust beSend&T: SendiffT: Sync, soPlumeRocket/Connectionmust beSyncPlumeRocketcontains aConnection, andConnectioncontains a dieselPgConnection, which is notSync.The approach demonstrated here is to change every
&PlumeRocketor&Connectionto an&mut PlumeRocketor&mut Connection.&mut TisSendifTisSend, so the problem is eliminated:Send.&mut PlumeRocketor an&mut Connectionheld across anawaitpoint&mut PlumeRocket/&mut Connectionmust beSend&mut T: SendiffT: Send, soPlumeRocket/Connectionmust beSendPlumeRocketcontains aConnection, andConnectioncontains a dieselPgConnection, which isSend.Downsides
&PlumeRocketcould allow more work to be done in parallel, at least in the future. It does not look like that is currently the case, since every call to the database blocks anyway.FromIdandInbox. I know relatively little about the overall structure of this code, so this could be incorrect or inconvenient in ways I don't know about!&->&mutchange. A different solution that keeps&in more places would be easier to work with overall.asyncfns, which can cause issues ranging from degraded performance to deadlocks.Alternatives
Mutexaround theConnectionsomewhere. Uncontended mutexes (which this one should be) are not a huge performance concern, butMutexmay be at least as or more unwieldy than this solution throughout the code.Connectionwith an API likeconn.run(|c| Post::load(&c)).await, whererunhandles the synchronization. This has similar tradeoffs to aMutex, is probably the most inconvenient option in terms of overall code changes, and is also a significant chunk of new code to write and debug. However, it has the advantage of being capable of fixing the blocking-in-async-fn problem.I think the best way to handle sql connections would be to have worker threads that are basically dedicated to that, and have a mpsc channel through which requests can be send to them, alongside a one shot channel that allow to return a result.
This is basically how actors work (like in Erlang and derivative, or the Actix lib for Rust), it would allow to keep
&, would properly handle blocking operation out of async context, and maybe allow to compile both Postgresql and Sqlite in the same binary (however this would also be a lot of work, not that much new code, but lots of moving things around)Yeah, I think that's more or less the direction I was going with "wrap
Connectionwith an API likeconn.run(|c| Post::load(&c)).await". I agree that it's a nicer overall solution, with the biggest drawback being:🤷♀️
we have come this far, we might as well do it right.
View command line instructions
Checkout
From your project repository, check out a new branch and test the changes.Merge
Merge the changes and update on Forgejo.Warning: The "Autodetect manual merge" setting is not enabled for this repository, you will have to mark this pull request as manually merged afterwards.