CASSSIDECAR-377: Implement job coordination for cluster-wide operations#360
CASSSIDECAR-377: Implement job coordination for cluster-wide operations#360andresbeckruiz wants to merge 6 commits into
Conversation
0e36849 to
817bf51
Compare
|
|
||
| // New job is submitted for all cases when we do not have a corresponding downstream job | ||
| jobTracker.computeIfAbsent(job.jobId(), jobId -> { | ||
| OperationalJob tracked = jobTracker.computeIfAbsent(job.jobId(), jobId -> job); |
There was a problem hiding this comment.
do we need to remove from jobTracker if there's a coordination conflict ? Or perhaps should we just add to jobTracker in case the tryCoordination was successful, so tryCoordination should come before jobtracker.computeIfAbsent ?
There was a problem hiding this comment.
This leaves stale job entry in CREATED state if the coordination fails.
There was a problem hiding this comment.
Would it make sense to mark the job as FAILED if coordination fails? And set the failureReason to indicate that the job was not able to start due to coordination failure?
There was a problem hiding this comment.
Coordination now happens before tracking and jobs that fail coordination are now marked as FAILED, addressed in 3661c4a
| { | ||
| if (job.requiresCoordination()) | ||
| { | ||
| Preconditions.checkState(coordinator != null, |
There was a problem hiding this comment.
Preconditions throws illegal state exception, which is not handled in the caller
There was a problem hiding this comment.
No more unhandled IllegalStateException, addressed in 3661c4a
| }; | ||
|
|
||
| manager.trySubmitJob(job, onComplete, executorPool.service(), SecondBoundConfiguration.parse("5s")); | ||
| assertThat(latch.await(10, TimeUnit.SECONDS)).isTrue(); |
There was a problem hiding this comment.
Also verify that tracker doesn't have entry for this job after conflict detected.
There was a problem hiding this comment.
Jobs are now marked as FAILED if coordination fails, so no conflict will happen as inflightJobsByOperation does not return completed jobs. Added
assertThat(tracker.inflightJobsByOperation(job.name())).doesNotContain(job);
in 3661c4a to confirm
| { | ||
| Preconditions.checkState(coordinator != null, | ||
| "Job requires coordination but no OperationalJobCoordinator is configured"); | ||
| boolean activated = coordinator.trySetActive(job.operationType(), job.jobId()); |
There was a problem hiding this comment.
I am afraid to merge this PR without calling clearActive. If we delay adding that in a subsequent PR and if someone enables requiresCoordination() for any job meanwhile, then no more further operations will be allowed. I would recommend implementing calling clearActive in the same PR.
a2bd0e1 to
30a4292
Compare
| @Nullable | ||
| private final OperationalJobCoordinator coordinator; |
There was a problem hiding this comment.
The nullable OperationalJobCoordinator feels like a bit of a smell to me. It seems like the goal here is to support backwards compatibility for the OperationalJobManager for users of the OperationalJobManager to not have to include coordination (e.g., for existing decommission jobs), am I right about that?
If so, I'd suggest that instead of having a null OperationalJobCoordinator, we have a second implementation, DisabledOperationalJobCoordinator or something similar, that fails all coordination tasks with an error saying that coordination is not currently supported by this sidecar instance (and maybe how to configure coordination if the user wants to have coordinated jobs).
This way we make the coordination enabled / disabled logic part of the behavior of the coordinator itself, as opposed to having a null dependency here. It can also clean up all accesses to the OperationalJobCoordinator as we no longer have to worry about it being null.
There was a problem hiding this comment.
Good idea. Replaced the @Nullable OperationalJobCoordinator with a DisabledOperationalJobCoordinator in 405a93d
To clarify, backwards compatibility for existing uncoordinated jobs (eg: decommission) is already handled by requiresCoordination() == false, so they short circuit before touching the coordinator. Therefore, the DisabledOperationalJobCoordinator only matters for a job requiring coordination submitted to an instance without coordination support.
Also updated this patch to bind the OperationalJobCoordinator to the DisabledOperationalJobCoordinator. Configuration to enable this class (as well as durable tracking) will be added in CASSSIDECAR-378.
e4bf6fa to
509b15b
Compare
| { | ||
| if (ar.succeeded() && Boolean.TRUE.equals(ar.result())) | ||
| { | ||
| job.asyncResult().onComplete(result -> releaseActiveOperationLock(job)); |
There was a problem hiding this comment.
requiresCoordination() is a clean job-level flag the manager just reads.
The release side isn't symmetric though, as trySubmitJob always auto-releases on local completion, with no way for a job to opt out. That's right for today's single-node jobs, but doesn't match clearActive's javadoc (orchestration-layer clearing for jobs that finish elsewhere).
Rather than just documenting that gap, could we add a parallel hook for release?
e.g. releasesOnCompletion(), default true; the manager just reads it instead of special-casing job types, so a future distributed job can skip the automatic release without any change to OperationalJobManager.
1bd9057 to
58bb7d4
Compare
58bb7d4 to
5d5afc6
Compare
CASSSIDECAR-377
Original PR made against CASSSIDECAR-373 branch with review comments: andresbeckruiz#2.
Changes
OperationalJobCoordinatorinterfaceStorageOperationalJobCoordinator: Implementation that delegates toStorageProvider's compare and set based methods to acquire a lock for an active operationOperationalJob.operationType(): New abstract method returningOperationTypeenum, implemented by all concrete jobsOperationalJobManagerintegration: If a job requires coordination, the manager acquires the active lock via the coordinator before execution; throwsOperationalJobConflictExceptionif rejectedStorageOperationalJobCoordinatorand coordinator integration inOperationalJobManagerTestThis ticket only covers the job activation path when a job is submitted to be executed immediately. Clearing locks after completion and status update activation will be implemented in later tickets (CASSSIDECAR-378, CASSSIDECAR-379).
Future Work