sirius.biz.locks.Locks Maven / Gradle / Ivy
Show all versions of sirius-biz Show documentation
/*
* Made with all the love in the world
* by scireum in Remshalden, Germany
*
* Copyright by scireum GmbH
* http://www.scireum.de - [email protected]
*/
package sirius.biz.locks;
import sirius.kernel.di.std.Framework;
import sirius.kernel.di.std.Part;
import sirius.kernel.di.std.Register;
import sirius.kernel.health.Log;
import sirius.kernel.health.metrics.MetricProvider;
import sirius.kernel.health.metrics.MetricsCollector;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.time.Duration;
import java.time.LocalDateTime;
import java.util.List;
/**
* Provides a central framework to obtain and manage named locks.
*
* These locks can either be distributed (via SQL or REDIS) or held locally. The implementation is provided via a {@link
* LockManager}.
*/
@Framework("biz.locks")
@Register(classes = {Locks.class, MetricProvider.class})
public class Locks implements MetricProvider {
private static final Duration LONG_RUNNING_LOGS_THRESHOLD = Duration.ofMinutes(30);
public static final Log LOG = Log.get("locks");
@Part(configPath = "locks.manager")
private LockManager manager;
/**
* Tries to acquire the given lock in the given timeslot.
*
* A sane value for the timeout might be in the range of 5-50s, highly depending on the algorithm
* being protected by the lock. If the value is null, no retries will be performed.
*
* @param lockName the name of the lock to acquire
* @param acquireTimeout the max duration during which retires will be performed
* @return true if the lock was acquired, false otherwise
*/
public boolean tryLock(@Nonnull String lockName, @Nullable Duration acquireTimeout) {
return manager.tryLock(lockName, acquireTimeout);
}
/**
* Boilerplate method to perform the given task while holding the given lock.
*
* See {@link #tryLock(String, Duration)} for details on acquiring a lock.
*
* If the lock cannot be acquired, nothing will happen (neighter the task will be execute nor an exception will be
* thrown).
*
* @param lock the name of the lock to acquire
* @param acquireTimeout the max duration during which retires will be performed
* @param lockedTask the task to execute while holding the given lock. The task will not be executed if the
* lock cannot be acquired within the given period
*/
public void tryLocked(@Nonnull String lock, @Nullable Duration acquireTimeout, @Nonnull Runnable lockedTask) {
if (tryLock(lock, acquireTimeout)) {
try {
lockedTask.run();
} finally {
unlock(lock);
}
}
}
/**
* Determines if the given lock is currently locked.
*
* @param lock the lock to check
* @return true if the lock is currently active, false otherwise
*/
public boolean isLocked(@Nonnull String lock) {
return manager.isLocked(lock);
}
/**
* Releases the lock.
*
* @param lock the lock to release
*/
public void unlock(String lock) {
unlock(lock, false);
}
/**
* Releases the given lock.
*
* @param lock the lock to release
* @param force if true, the lock will even be released if it is held by another node. This is a very
* dangerous operation and should only be used by maintenance and management tools.
*/
public void unlock(String lock, boolean force) {
manager.unlock(lock, force);
}
@Override
public void gather(MetricsCollector collector) {
List locks = getLocks();
LocalDateTime limitForAcquired = LocalDateTime.now().minus(LONG_RUNNING_LOGS_THRESHOLD);
collector.metric("locks-count", "Active Locks", locks.size(), null);
collector.metric("locks-long-running",
"Long locks",
locks.stream().filter(l -> l.getAcquired().isBefore(limitForAcquired)).count(),
null);
}
/**
* Returns a list of all currently held locks.
*
* @return a list of all locks
*/
public List getLocks() {
return manager.getLocks();
}
}