Skip to content
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

Merged
merged 6 commits into from
Jul 5, 2018
Merged

PAYARA-2889 Defer OpenAPI Scanning Until Endpoint Visit #2916

merged 6 commits into from
Jul 5, 2018

Conversation

MattGill98
Copy link
Contributor

  • Deferred OpenAPI scanning until the /openapi endpoint is visited.
  • Allowed document creation for apps deployed while the OpenAPI service is disabled, since it's now created on endpoint visiting.
  • Added a null check to prevent potential @Produces errors.

@MattGill98 MattGill98 added this to the Payara 5.183 milestone Jul 2, 2018
@MattGill98 MattGill98 self-assigned this Jul 2, 2018
@MattGill98 MattGill98 requested a review from MeroRai July 2, 2018 11:27
@MattGill98
Copy link
Contributor Author

jenkins test please

@payara-ci
Copy link
Contributor

Quick build and test passed!


private synchronized OpenAPI getDocument() throws InterruptedException, ExecutionException, TimeoutException {
if (!document.isDone()) {
executor.submit(new OpenApiBuilder(this, document));
Copy link
Contributor

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.

Copy link
Contributor Author

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.

Copy link
Contributor Author

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!

Copy link
Contributor

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
}

Copy link
Contributor Author

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.

Copy link
Contributor

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.

@MattGill98
Copy link
Contributor Author

jenkins test please

@payara-ci
Copy link
Contributor

Quick build and test passed!


@Override
public void run() {
if (!future.isDone()) {
Copy link
Contributor

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));
Copy link
Contributor

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.

@OndroMih
Copy link
Contributor

OndroMih commented Jul 4, 2018

Hi @MattGill98 the current solution is thread-safe and I'll approve.

@MattGill98
Copy link
Contributor Author

jenkins test please

@payara-ci
Copy link
Contributor

Quick build and test passed!

@MattGill98 MattGill98 merged commit 9bf2423 into payara:master Jul 5, 2018
Cousjava pushed a commit that referenced this pull request Jul 9, 2018
* 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.
@MattGill98 MattGill98 deleted the PAYARA-2889-Defer-OpenAPI-Scanning-Until-Endpoint-Visit branch February 25, 2019 09:31
@MattGill98 MattGill98 restored the PAYARA-2889-Defer-OpenAPI-Scanning-Until-Endpoint-Visit branch February 25, 2019 09:31
@MattGill98 MattGill98 deleted the PAYARA-2889-Defer-OpenAPI-Scanning-Until-Endpoint-Visit branch February 25, 2019 09:31
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants