lukas-krecan / ShedLock

Distributed lock for your scheduled tasks
Apache License 2.0
3.64k stars 514 forks source link

Provide more generic lock annotation for non scheduler based contexts #899

Open holgerstolzenberg opened 2 years ago

holgerstolzenberg commented 2 years ago

We are using ShedLock in our projects and like it pretty much. It's very mature and neatly integrated.

Yesterday I came to the point where I needed a distributed lock in a non scheduler based context.

The use case is to create database table partitions on startup of an Spring boot app by a method annotated with @EventListener(ApplicationStartedEvent.class).

@Transactional
@EventListener(ApplicationStartedEvent.class)
@SchedulerLock(name = INIT_PARTITIONS_LOCK_NAME)
public void init() {
  // lock might not be there for tests where scheduling is disabled
  if (isLockProviderAvailable()) {
    LockAssert.assertLocked();
    log.debug("Distributed lock for partition creation has been obtained");
  }

  log.info("Creating necessary partitions on startup...");
  service.forPartitionCreation().forEach(this::createPartition);
  log.info("All partitions have been successfully created");
}

I know that ShedLock is primarily designed for scheduler based stuff, but I gave it a shot and tried to use it as a "regular" distributed lock for the partition creation. What can I say - it worked.

From this situation a few thoughts arise that might end in a feature request for this project or just documentation stuff, so please forgive me if that is not a typical Github issue.

These are the points that I am thinking about:

Sure I could add another framework for providing the distributed lock or implement something custom in our code base. But why if ShedLock already has everything in its package? Looking at for example https://github.com/alturkovic/distributed-lock you can see that it is pretty close to what ShedLock offers but require an extra lock table if used with JDBC.

I'd rather like to start a discussion upon this to decide whether to actually add a refined issue. If you see a better place to post this, please tell me.

holgerstolzenberg commented 2 years ago

Update:

For the moment I use a pseudo annotation:

package de.dehst.platform.waiting.area.service.core;

import static java.lang.annotation.ElementType.METHOD;
import static java.lang.annotation.RetentionPolicy.RUNTIME;

import net.javacrumbs.shedlock.spring.annotation.SchedulerLock;
import org.springframework.core.annotation.AliasFor;

import java.lang.annotation.Documented;
import java.lang.annotation.Inherited;
import java.lang.annotation.Retention;
import java.lang.annotation.Target;

@Documented
@Inherited
@Retention(RUNTIME)
@Target(METHOD)
@SchedulerLock
public @interface DistributedLock {
  @AliasFor(annotation = SchedulerLock.class) String name();
}

That way it looks a bit cleaner at the places where it gets declared.

Aloren commented 2 years ago

JFYI We are using shedlock in production without @Scheduled annotation, because we have dynamic jobs. Works amazing.

lukas-krecan commented 2 years ago

Thanks for feedback. The workaround with the pseudoanotation is a grat idea. I have to think about it. I do not want to ofically declare that it's possible to use it as a generic "lock".

I am afraid that there will be some new edgecases which will force me to bend the library.

Morover, I do not know how to call it. It's not a lock. If it's not available, the process does not wait but just skips the execution. Any ideas about the name?

EnTaroJankov commented 2 years ago

Having 'TryLock' in the name seems to be the most popular way to convey a lock does not wait. E.g. in java.util.concurrent.locks

KSH-code commented 1 year ago

how about skip lock or no wait lock? https://dev.mysql.com/blog-archive/mysql-8-0-1-using-skip-locked-and-nowait-to-handle-hot-rows/

@lukas-krecan

pkgonan commented 1 year ago

@lukas-krecan Hi, is there any support plan about MySQL nowait Option?

lukas-krecan commented 1 year ago

No, as I understand it nowait can be used only in selects for update. ShedLock only uses INSERT and UPDATE