-
Notifications
You must be signed in to change notification settings - Fork 37
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
Instantiating Miden Client in Backend Causes Route Handlers to Fail #657
Comments
@Mirko-von-Leipzig @igamigo could you guys give it a look, I know that you have a lot of exp with Rust and multi-threading. If not you could you re-route to someone that can give a hand, thanks. |
I've been working on this, there's a version of the There might another problem with that version though. Specifically, all the async methods of the client will return Even with a full A possible workaround in this case is to create new instances of the client that all share the same sqlite database, this means that every client would share the data and be undistinguishable from each other. In this case an external lock could be used to make sure the client is only accessed by one thread at a time. |
I don't have the full context, but this reminded me of the discussion we had a while back in #358 (comment). Would the |
Written by the Keom team: Keom<>Miden Asynchronous - Multithreading ProblemProblem exposureWhile developing the Keom backend, I encountered a significant issue with the Orderbook SDK that we have created and its integration into the Axum-based API. Specifically, many types within the Miden Client do not implement Send or Sync traits, which creates a roadblock when attempting to await functions in handler routes. ContextAxum relies on Tokio as the asynchronous runtime. Tokio, by default, uses a multithreaded runtime, requiring that all futures implement the Send trait to ensure they can be safely moved across threads. The Orderbook SDK that we created contains functions and data structures integral to managing orderbook operations. However, many of these types do not implement Send or Sync. This limitation prevents these types and functions from being used in Axum routes since the handler functions are expected to operate seamlessly in Tokio’s multithreaded environment. After opening a github issue, core developers proposed different solutions. I have tried implementing those solutions as trying to implement some of the solutions that I thought would work. In the next section, I will explain each and one of them. Tomyrd-send-sync-client BranchThe issue arises because the new client introduces significant changes, including new methods and removal of old ones. While attempting to refactor the SDK to align with version 0.7, I encountered several challenges due to the lack of examples or documentation for implementing certain features. For instance, the AccountTemplate type no longer exists, which left me unsure about how to create faucets and user accounts under the new implementation. As Tomyrd stated: “This is the latest version of the client, so there will be some interface changes from v0.6” This turned out to be a bigger issue than expected. SharableClientInitially, I assumed that SharableClient was something provided by the Miden Client itself. However, after searching for it, I realized that this is not the case. Upon reading through a related discussion, I discovered that SharableClient needs to be implemented by the developer working on the application. Making the whole application single-threadedThe initial idea was to make the entire application run on a single thread, eliminating the need for Send and Sync (Single-threaded Tokio). After introducing the necessary macro change for the main function, the problem still persisted, which was confusing. Why would Send and Sync still be required in a single-threaded environment? This had me raise the question on the Tokio Discord server. I received two responses. The first suggested using the current-thread flavor of Tokio’s runtime along with LocalSet to remove the need for Send (LocalSet). I attempted to wrap app instantiation in the main function within a LocalSet, but it didn’t give me the results I was hoping for. Honestly, I can’t explain why this approach failed, as it goes beyond my expertise. The second suggestion was to create custom mpsc channels to handle communication. In this approach, the sender would be given to the handler, and the receiver would be a thread. While this method might promise, implementing would require more time to explore the best approach and understanding a problem to its fundamentals, as this is not a type of problem I frequently encounter |
I resumed working on this issue today, I hope to bring a solution in the coming days. In the meantime, I think there's a possible workaround that might work with the current |
I would actually like to understand the use case for this a bit better - what exactly are we trying to do here? I can think of a couple of scenarios (but not sure if this is an exhaustive list):
If it is the first case, all requests should be synchronized before they get to the client. That is the client runs in a single thread and the front end puts it behind a mutex or something like that for the duration of the entire request. If this creates latency issues (because we need to both execute and prove the transactions before we can release the client), we'll need to re-think how transaction submitting process works. For example, people may want to execute transactions, apply them to the local DB w/o generating proofs. The proofs can then be generated concurrently and transactions submitted to the chain as the proofs are generated (this model is much more complicated than what we do now because we need to handle potential state rollbacks if transactions get discarded by the node). If it is the second case, then one solution is to instantiate a separate client for each account because the current client is not really set up to handle concurrent access to the accounts it manages. Though, we could try to explore how to enable something like this. @OgnjenCBS, @phklive - which (if any) of the above scenarios are we trying to handle? |
Feature description
The problem occurs when instantiation of Miden Client is attempted in a backend server (Axum). The core issue lies in the fact that the SEND and SYNC traits are not implemented for several types in the Miden Client, so any usage of created async functions in Miden SDK for Orderbook will not be able to be awaited on the server side.
This is an example of the code that will produce an error
Most of the errors will show in this form
the trait
Syncis not implemented for
(dyn miden_tx::prover::TransactionProver + 'static), which is required by
impl Future<Output = ()>: Send``the trait
Sendis not implemented for
(dyn miden_tx::prover::TransactionProver + 'static), which is required by
impl Future<Output = ()>: Send``Environment:
miden-client: version 0.6.0
miden-objects: version 0.6.0
axum: version 0.7.9
tokio: version 1.0
Why is this feature needed?
No response
The text was updated successfully, but these errors were encountered: