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

Store async upload job in the request's thread #1407

Merged
merged 2 commits into from
Dec 15, 2023

Conversation

IvanBorislavovDimitrov
Copy link
Contributor

No description provided.

.id(entry.getId())
.delete();
} catch (Exception e) {
LOGGER.error(Messages.ERROR_OCCURRED_WHILE_DELETING_JOB_ENTRY, e);
Copy link
Contributor

@radito3 radito3 Nov 24, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Apart from logging the error, should we handle this case? If a job fails to be submitted but also fails to be deleted from the DB, this would lead to a resource leak.
Fetching the job would always return 200 with state "initial" but it will never run, so a client would hang indefinitely.

@IvanBorislavovDimitrov IvanBorislavovDimitrov force-pushed the async-job branch 2 times, most recently from cade49d to c24c5ae Compare December 7, 2023 08:04
Comment on lines +142 to +151
if (runningTasks.get(existingJob.getId()) != null) {
LOGGER.info(Messages.ASYNC_UPLOAD_JOB_EXISTS, urlWithoutUserInfo, existingJob);
return ResponseEntity.status(HttpStatus.SEE_OTHER)
.header(HttpHeaders.LOCATION, getLocationHeader(spaceGuid, existingJob.getId()))
.header("x-cf-app-instance", configuration.getApplicationGuid() + ":" + existingJob.getInstanceIndex())
.build();
} else {
LOGGER.warn(Messages.THE_JOB_EXISTS_BUT_IT_IS_NOT_RUNNING_DELETING);
deleteAsyncJobEntry(existingJob);
}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extract in a new method

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Extracted another part of the method, because here it returns

.bytes(count.get())
.build());
}
var jobWithLatestState = getJob(job.getId(), spaceGuid, namespace);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sonarcloud reports that jobWithLatestState can be null. I had noticed that at the beginning AsyncUploadJobEntry is loaded from the db, so we can reuse the object instead of calling db twice. What is the possibility to have different state of AsyncUploadJobEntry during several checks which does not perform any external calls to other services?

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 idea is to fetch the new state of the object from the database as it should be changed because the Future task is done. This covers the race condition between updating/getting the job
I do not think the variable can be null, we've already checked it

@@ -233,20 +268,29 @@ private AsyncUploadJobEntry getExistingJob(String spaceGuid, String namespace, S
.user(SecurityContextUtil.getUsername())
.namespace(namespace)
.url(url)
.instanceIndex(configuration.getApplicationInstanceIndex())
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What will happen during bg update of deploy-service and both versions are up and running? Then app instance index will match but job won't exist on one of the app instances.

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 think the request will fail because of the x-cf-app-instance, since it points to the application that we're stopping which will retry the upload. When both run it will call the right one

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, tested it with simulated bg-deploy of the deploy-service.
When 2 apps are running it still sends requests to the one that the upload started because of x-cf-app-instance
When the old one is stopped the router returns 400 which retries the whole upload and succeeds, 400 is returned again because of x-cf-app-instance

public static final String JOB_0_WAS_NOT_FOUND_IN_THE_RUNNING_TASKS = "Job \"{0}\" was not found in the running tasks";
public static final String JOB_IS_NOT_BEING_EXECUTED = "Job is not being executed.";
public static final String JOB_0_EXISTS_IN_STATE_1_BUT_DOES_NOT_EXISTS_IN_THE_RUNNING_TASKS = "Job \"{0}\" exists in state \"{1}\" but does not exists in the running tasks";
public static final String JOB_THREAD_IS_NOT_RUNNING_BUT_STATE_IS_STILL_IN_PROGRESS_UPLOAD_FAILED = "Job thread is not running but state is still in progress. Upload failed...";
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we are using multiple dots only when something continue to run on background. I think this is not the case here, it will retry only if client retry http request, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

correct

Copy link

SonarCloud Quality Gate failed.    Quality Gate failed

Bug C 1 Bug
Vulnerability A 0 Vulnerabilities
Security Hotspot A 0 Security Hotspots
Code Smell A 6 Code Smells

58.1% 58.1% Coverage
0.0% 0.0% Duplication

idea Catch issues before they fail your Quality Gate with our IDE extension sonarlint SonarLint

Copy link
Contributor

@theghost5800 theghost5800 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do not forget to asses findings in sonarcloud after merge

@IvanBorislavovDimitrov IvanBorislavovDimitrov merged commit 0573010 into master Dec 15, 2023
5 of 6 checks passed
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.

3 participants