-
Notifications
You must be signed in to change notification settings - Fork 166
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
Concurrent Search Bug #393
Comments
I debugged the source code and found that the cause of the error was the concurrency problem in the spark/src/Spark.Engine/Service/FhirServiceExtensions/SnapshotPaginationProvider.cs Lines 15 to 35 in 6ac316e
the Call chain is: AsyncFhirService -> PagingService -> SnapshotPaginationProvider Although SnapshotPaginationProvider is injected Transient , because AsyncFhirService is a Singleton , SnapshotPaginationProvider is also a Singleton .spark/src/Spark.Engine/Service/AsyncFhirService.cs Lines 370 to 390 in 212d071
At present, I have changed |
It was singleton in good old classic Spark (.NET FW), and probably therefore it is singleton in the .NET Core/Standard version of Spark. Actually I do not see a good reason for |
But creating an spark/src/Spark.Engine/Service/AsyncFhirService.cs Lines 28 to 43 in 212d071
This has a effect on Performance. |
Yes, that is a concern. I have not measured the effect it would have on performance, but yes that would be the concern. |
Hi, For example, I have 20 Device resource in DB. testFhir(): void {
for (let i = 0; i <20; i++) {
this.http.get('https://esp32fhir.azurewebsites.net/fhir/Device?identifier=' + i.toString().padStart(12, '0'))
.toPromise()
.then((res: any) => {
console.log(i, res.entry[0].resource);
});
}
} Andy |
Hi @whyfate, Could you tell me how you changed AsyncFhirService to Transient to solve the problem temporarily ? Andy |
@one0410 I modified the source code.
services.TryAddTransient<IAsyncFhirService, AsyncFhirService>(); |
@whyfate how did that affect the performance? |
@whyfate You are right, the performance is terrible. |
@one0410, absolutely not. I haven't yet had time to look into the root cause of this. If any of you have time to do that it would be much appreciated. Anyways, I'll put it into the current sprint for the next release |
I have an immature suggestion, which is to pass
Bundle GetPage(Snapshot snapshot,int? index = null, Action<Entry> transformElement = null); Replacing spark/src/Spark.Engine/Service/FhirServiceExtensions/SnapshotPaginationProvider.cs Lines 29 to 58 in e130c88
But emmm...bad code warning!!! |
I've done some research and can confirm that I am seeing the error as well. I tried putting a SemaphoreSlim around the code in AsyncFhirService.SearchAsync (as a hot fix), it helps, but it slows it down since it forces the requests to run synchronously one-by-one. I need to try and reproduce this with FhirServiceService to see if we had this problem before we added AsyncFhirService |
This problem is |
This is fixed in both STU3 and R4. If you are compiling from source, please verify by pulling. If you are using the NuGet packages I will create a new release today Summarized I split ISnapshotPaginationProvider and ISnapshotPagination into two implementations making sure as @whyfate pointed out that Snapshot is not affected by the singleton behavior of ISnapshotPaginationProvider. There is a more lengthy explanation in the commit/PR |
Thank you very much. This does help me a lot. You are really amazing. |
@kennethmyhra Hi,I saw your implementation,I don't think it's good to directly a new services.AddTransient<ISnapshotPaginationProvider, SnapshotPaginationProvider>(); public class PagingService : IPagingService
{
private readonly ISnapshotStore _snapshotstore;
private readonly IServiceProvider _serviceProvider;
public PagingService(ISnapshotStore snapshotstore, IServiceProvider serviceProvider)
{
_snapshotstore = snapshotstore;
_serviceProvider = serviceProvider;
}
public ISnapshotPagination StartPagination(Snapshot snapshot)
{
return Task.Run(() => StartPaginationAsync(snapshot)).GetAwaiter().GetResult();
}
public ISnapshotPagination StartPagination(string snapshotkey)
{
return Task.Run(() => StartPaginationAsync(snapshotkey)).GetAwaiter().GetResult();
}
public async Task<ISnapshotPagination> StartPaginationAsync(Snapshot snapshot)
{
if (_snapshotstore != null)
{
await _snapshotstore.AddSnapshotAsync(snapshot).ConfigureAwait(false);
}
else
{
snapshot.Id = null;
}
var snapshotPaginationProvider = _serviceProvider.GetRequiredService<ISnapshotPaginationProvider>();
return snapshotPaginationProvider.StartPagination(snapshot);
}
public async Task<ISnapshotPagination> StartPaginationAsync(string snapshotkey)
{
if (_snapshotstore == null)
{
throw new NotSupportedException("Stateful pagination is not currently supported.");
}
var snapshotPaginationProvider = _serviceProvider.GetRequiredService<ISnapshotPaginationProvider>();
return snapshotPaginationProvider.StartPagination(await _snapshotstore.GetSnapshotAsync(snapshotkey).ConfigureAwait(false));
}
} |
@whyfate the plan is to do this in the next version. While I agree with you - right now the only downside is that you can't make your own implementation of the interface I also see now that you are referring to some other interface ( |
I see,thanks. |
Describe the bug
Such as the title
To Reproduce
it's my test code
Expected behavior
all print {j}---success
Screenshots
The text was updated successfully, but these errors were encountered: