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

[FEATURE] - Allow Disabling Global Locker At Job Level #808

Open
seinshah opened this issue Dec 19, 2024 · 1 comment
Open

[FEATURE] - Allow Disabling Global Locker At Job Level #808

seinshah opened this issue Dec 19, 2024 · 1 comment
Labels
enhancement New feature or request

Comments

@seinshah
Copy link

Is your feature request related to a problem? Please describe

There are occasions that we want our general schedulers to have a locking mechanism and instances of scheduler run only one job across all instances for all the defined job except some of them. In other words, let a specific job to be scheduled by all the scheduler across different instances.

Describe the solution you'd like

1. Edit WithDistributedJobLocker

gocron/job.go

Lines 552 to 560 in c180381

func WithDistributedJobLocker(locker Locker) JobOption {
return func(j *internalJob, _ time.Time) error {
if locker == nil {
return ErrWithDistributedJobLockerNil
}
j.locker = locker
return nil
}
}

func WithDistributedJobLocker(locker Locker) JobOption {
	return func(j *internalJob, _ time.Time) error {
		if locker == nil {
			j.disableGlobalLocker = true // new struct property
		} else {
		       j.locker = locker
                }
		return nil
	}
}

2. Update executor.runJob to respect the above

gocron/executor.go

Lines 373 to 391 in c180381

} else if j.locker != nil {
lock, err := j.locker.Lock(j.ctx, j.name)
if err != nil {
_ = callJobFuncWithParams(j.afterLockError, j.id, j.name, err)
e.sendOutForRescheduling(&jIn)
e.incrementJobCounter(j, Skip)
return
}
defer func() { _ = lock.Unlock(j.ctx) }()
} else if e.locker != nil {
lock, err := e.locker.Lock(j.ctx, j.name)
if err != nil {
_ = callJobFuncWithParams(j.afterLockError, j.id, j.name, err)
e.sendOutForRescheduling(&jIn)
e.incrementJobCounter(j, Skip)
return
}
defer func() { _ = lock.Unlock(j.ctx) }()
}

The last else would be:

...
else if e.locker != nil && !j.disableGlobalLocker {
        ...
}

Describe alternatives you've considered

The only way I have came to is to implement a custom locker on my side and drop using the locking mechanism of gocron as these methods and functions are not part of the package's public API.

Additional context

I'd be happy to open a PR and address this enhancement.
This feature would allow to run some of our jobs in batch mode by all the instance (and let the job itself decide how they want to divide and conquer if necessary) and some of our jobs only to be run by one instance at each point in time.

@seinshah seinshah added the enhancement New feature or request label Dec 19, 2024
@JohnRoesler
Copy link
Contributor

hey @seinshah I think the enhancement seems reasonable. Any of the job options are currently able to be set globally with WithGlobalJobOptions. So, Locker could have been created at the job level originally and then allowed to be set globally. Anyway, that aside, I'm good with having it available at a job level.

I look forward to your PR!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants