-
Notifications
You must be signed in to change notification settings - Fork 306
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
PAYARA-2889 Defer OpenAPI Scanning Until Endpoint Visit #2916
PAYARA-2889 Defer OpenAPI Scanning Until Endpoint Visit #2916
Conversation
jenkins test please |
Quick build and test passed! |
|
||
private synchronized OpenAPI getDocument() throws InterruptedException, ExecutionException, TimeoutException { | ||
if (!document.isDone()) { | ||
executor.submit(new OpenApiBuilder(this, document)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like multiple tasks for the same document can be submitted, right? Also, if the executor uses multiple threads in a pool, the tasks can be executed in parallel.
If I'm right, then we have to ensure that the document is submitted to the executor only once.
Also, just in case, OpenApiBuilder.run() should only do its job only if the document is not yet done / the completableFuture is not completed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The method is synchronized for this reason, it can only be run in one thread at a time. Since the wait loop is in there, all threads will wait for the document to be built.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I've just added the second check you asked for anyway, since there's no harm in adding it!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I missed that the code is in the !document.isDone block so it's only executed when document isn't done yet.
However, this is not thread safe because it's submitted to the executor, which runs the builder in another thread. While a document is being generated, getDocument can be executed in another thread, which will schedule another builder.
Safe method to run this only once is to add a handler to the CompletableFuture document
immediately when it's created and then only complete the future in the executor. The handler would be executed only the first time the future is completed.
Something like in the constructor:
this.document = new CompletableFuture<>();
this.document.thenRun(new OpenApiBuilder(this)); // no need to pass this.document as argument as the builder doesn't need to interact with it
and in getDocument() simply:
if (! this.document.isDone() ) { // this condition is only to optimize so that the task isn't submitted to the executor at all because it would be ignored anyway
executor.submit( () -> this.document.complete(null) ); // this triggers the above handler only the first time when the document is completed, otherwise it's ignored
}
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I believe it's already thread safe. It submits the task to the executor, and then waits in the same method for it to be finished.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not entirely thread-safe, see my comment below on line 283.
jenkins test please |
Quick build and test passed! |
|
||
@Override | ||
public void run() { | ||
if (!future.isDone()) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This check is not thread safe - if the executor has more threads, the run() method can be executed concurrently. Before the first one is finished, the future isn't done so the second one will also try to do the job and they will both run in parallel.
The call to future.isDone() isn't atomic and the future might be being completed in a parallel thread while not yet done.
|
||
private synchronized OpenAPI getDocument() throws InterruptedException, ExecutionException, TimeoutException { | ||
if (!document.isDone()) { | ||
executor.submit(new OpenApiBuilder(this, document)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not entirely thread-safe, see my comment below on line 283.
Hi @MattGill98 the current solution is thread-safe and I'll approve. |
jenkins test please |
Quick build and test passed! |
* Merge pull request #2916 from MattGill98/PAYARA-2889-Defer-OpenAPI-Scanning-Until-Endpoint-Visit PAYARA-2889 Defer OpenAPI Scanning Until Endpoint Visit * Removed PayaraExecutorService reference.
/openapi
endpoint is visited.@Produces
errors.