Class CurationLockServiceImpl

java.lang.Object
ubic.gemma.persistence.service.common.auditAndSecurity.curation.CurationLockServiceImpl
All Implemented Interfaces:
CurationLockService

@Service public class CurationLockServiceImpl extends Object implements CurationLockService
Default CurationLockService.

Written straight through the session rather than via a curatable update path, and emitting no audit event — see the interface for why both matter.

  • Constructor Details

    • CurationLockServiceImpl

      @Autowired public CurationLockServiceImpl(SessionFactory sessionFactory)
  • Method Details

    • acquire

      @Transactional public CurationLock acquire(Investigation ee, String lockedBy, boolean steal, int ttlMinutes)
      Description copied from interface: CurationLockService
      Take or refresh the lock.
      Specified by:
      acquire in interface CurationLockService
      Parameters:
      steal - permit taking a lock another curator currently holds. Always available to callers by design — there is no unlock ceremony to forget, and a steal destroys nothing, since the displaced curator's DRAFT is a separate row.
      Returns:
      the granted lock
    • acquire

      @Transactional public CurationLock acquire(Investigation ee, String lockedBy, boolean steal, int ttlMinutes, @Nullable String runId, @Nullable String agentName)
      Description copied from interface: CurationLockService
      As CurationLockService.acquire(Investigation, String, boolean, int), recording WHAT is taking the lock as well as who it is for.

      runId / agentName are null for a person, which is how a reader tells a curator from a job. See CurationLock.getRunId() for why this is stored rather than derived.

      Specified by:
      acquire in interface CurationLockService
    • refresh

      @Transactional public Optional<CurationLock> refresh(Investigation ee, String heldBy, int ttlMinutes)
      Description copied from interface: CurationLockService
      Extend the caller's existing lease without taking one they do not hold. Called on every draft autosave, so working holds the lock and walking away releases it.
      Specified by:
      refresh in interface CurationLockService
      Returns:
      the refreshed lock, or empty if heldBy does not hold it — a refresh must never quietly become an acquire, or an autosave would steal a lock the curator never asked for
    • release

      @Transactional public boolean release(Investigation ee, String heldBy)
      Description copied from interface: CurationLockService
      Release the lock if heldBy holds it.
      Specified by:
      release in interface CurationLockService
      Returns:
      whether a lock was released
    • forceRelease

      @Transactional public boolean forceRelease(Investigation ee)
      Description copied from interface: CurationLockService
      Release whoever holds it. For administrators.
      Specified by:
      forceRelease in interface CurationLockService
    • current

      @Transactional(readOnly=true) public Optional<CurationLock> current(Investigation ee)
      Description copied from interface: CurationLockService
      The current holder, or empty when the dataset is free.

      An expired row reads as empty rather than as a holder: nothing sweeps expiry, so "is it locked" has to mean "is there an unexpired claim".

      Specified by:
      current in interface CurationLockService
    • isHeldBy

      @Transactional(readOnly=true) public boolean isHeldBy(Investigation ee, @Nullable String username)
      Description copied from interface: CurationLockService
      Whether username holds an unexpired lock. This is what sign-off checks.
      Specified by:
      isHeldBy in interface CurationLockService
    • current

      @Nullable @Transactional(readOnly=true) public Map<Long, CurationLock> current(Collection<Long> investigationIds)
      Description copied from interface: CurationLockService
      The current holders of many datasets, keyed by dataset id, in ONE query.

      Exists because the question is asked about a LIST: the curation queue pages up to 1000 rows, and asking per row is 1000 round-trips to paint one screen. A dataset nobody holds is simply absent from the map rather than mapped to null.

      Same expiry rule as CurationLockService.current(Investigation) — a lapsed claim is not a holder — so a caller can treat presence in this map as "held right now" without re-checking dates.

      Specified by:
      current in interface CurationLockService