-
Notifications
You must be signed in to change notification settings - Fork 1.2k
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
loopback.getCurrentContext() returns null in MyModel.getDataSource() override, when querying model relation with { include: ... } filter #1961
Comments
Here's are the server stack traces for the Model.find() function calls that are executed via the remote-connector from the browser to the server.
Root-Query ... Model.find ... context is OK
Query Include-Filter ... { include: 'relation' } ... context is NULL
and also
the big difference that I can spot is the use of |
getCurrentContext() is pretty much deprecated and is highly unstable: #1676 |
You can use the alternative to inject remote context via options. |
Duplicate of loopbackio/loopback-datasource-juggler#657 |
Thanks for the replies.
Currently I am overriding the Model.getDataSource() function, I don't have access to the remote context there, so the workarround does not immediately solve my issue. I will have a look to see if I can achieve the same functionality that I have now, but without overriding getDataSource(). But that's just to say that there are currently usecases of loopback.getCurrentContext() that might not be covered by the workarround.
I see, it should really be marked as deprecated asap then in the code / docs ... I've seen so many threads/issues/workarrounds that all stem from getCurrentContext() not really being supported anymore. It would be helpful to let people know what they are getting into if they start using getCurrentContext() today. Regards |
I am closing this issue as its a duplicate of loopbackio/loopback-datasource-juggler#657 |
@drywolf
I don't really like this approach though, most importantly, I don't think it will scale well, and if a second remote operation is started before the first completes, the second will overwrite the data source in the global variable, and the first will read data from the wrong data source. So I would be really curious how you solved this problem, |
hi @eggerdo I did basically the same, this is a small playpen project that I used to evaluate and test the approach... The difference to your approach is that I don't use a global variable and I also do not override the getDataSource function anymore, instead I switch the data-source in the beforeRemote() hook of the models directly. About concurrency, I wrote a basic test that I can run from a browser. This basically just spams requests, switching between six data-sources repreatedly and checking if the returned data is consistent with what is expected to be returned for that data-source in the request header. This works pretty well up to now, but I'm also not a 100% certain that this solution covers all situations about request-concurrency cases. |
@drywolf |
I did a very quick test in the example project from above, and I think you are right about the PUT/id call. Client-Result-Log:
This is a corresponding debug log from the server where I logged out the relevant information in
Server-Log:
Strangely on the incorrect datasource does not produce a data inconsistency on the server, which I believe might be a special case because I am using the memory data-source for those tests. The behavior of the updateAttributes() call from the client's perspective is pretty off though. Since it uses an entity that was previously queried from datasource1 but uses this instance to update a different entity in datasource2. But from the perspective of the http-requests alone, it is still a consistent and valid transaction as far as I can tell. It would be interesting to see what happens with a real database connector, I would asume that data would get falsely updated / leaked from one datasource to another one. @eggerdo Which connector / datasource are you using ? Have you been able to create a test case where data actually breaks ? Cheers |
I just ran the same test code with a SQL data-source, the result is exactly the same as above. One thing that I also figured out tho is that if in the original data-source there is no entity with the same ID as of the entity in the datasource that you want to update, then the update will fail silently and no data will be changed anywhere. Client-Result-Log:
|
@drywolf |
Hi,
I'm currently working on a way to integrate a multi-tenancy usecase for a project that uses loopback.
(see the following discussion for details about the approach: https://groups.google.com/forum/#!msg/loopbackjs/KIhO2_W5dF4/bmY2CNkrBwAJ)
Basically we are overriding certain models' getDataSource() method and we then switch data-sources between multiple different MS-SQL data-sources (pointing to different schemas in the same DB in our case).
The information which data-source to return from our MyModel.getDataSource() override is retrieved by using the loopback context functionality ->
loopback.getCurrentContext()
In a request middleware we put a tenant-id into the context, later when the
MyModel.getDataSource()
is called we retrieve the context and look for the tenant-id, which tells us which data-source we should use for this request (we then attach the Model to the data-source that was determined).This works fine for the most part, but when it comes to querying relation-properties of models this does not work properly, because
loopback.getCurrentContext()
returns null in the target model of the relation. So for the origin-model of the query our getDataSource() override works fine and uses the correct data-source, but in the getDataSource() override of the model that is included via a relation in the query, the getCurrentContext() call just returns null because it can't find the context.I'm currently trying to debug into the depths of the loopback context functionality (specifically loopback/server/current-context.js, but I'm not really experienced with the CLS magic that is used to implement this functionality, so I'm not really progressing anywhere at the moment 😬
Can anyone please give some hints what I should look at to solve the bug ?
I tracked the callstack for the call to MyModel.getDataSource() that shows the bug, but I just don't know what to look out for to fix the issue and make the CLS/context functionality work for this case.
EDIT:
especially I'm looking at the chain(...) calls in loopback/server/current-context.js#L79/80.
I guess they are mixing in the context functionality into the data-juggler and remote-objects modules, but I can't grasp what exactly is happening there.
Thanks & Regards,
Wolfgang
The text was updated successfully, but these errors were encountered: