AutoPagerizeStateRepository.java
package net.sasasin.sreader.repository;
import static net.sasasin.sreader.jooq.Tables.AUTOPAGERIZE_DATASET;
import static net.sasasin.sreader.jooq.Tables.AUTOPAGERIZE_STATE;
import java.time.OffsetDateTime;
import java.util.Optional;
import net.sasasin.sreader.domain.AutoPagerizeActiveState;
import org.jooq.DSLContext;
import org.jooq.Record;
import org.springframework.stereotype.Repository;
/**
* Singleton active AutoPagerize dataset pointer. Prefer {@link #lockActiveState()} inside a service
* transaction before {@link #activateDataset(long)} when atomic switch is required.
*/
@Repository
public class AutoPagerizeStateRepository {
private static final short SINGLETON_ID = 1;
private final DSLContext dsl;
public AutoPagerizeStateRepository(DSLContext dsl) {
this.dsl = dsl;
}
public Optional<Long> findActiveDatasetId() {
return Optional.ofNullable(
dsl.select(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID)
.from(AUTOPAGERIZE_STATE)
.where(AUTOPAGERIZE_STATE.ID.eq(SINGLETON_ID))
.fetchOne(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID));
}
public AutoPagerizeActiveState findActiveState() {
return dsl.select(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID, AUTOPAGERIZE_STATE.ACTIVATED_AT)
.from(AUTOPAGERIZE_STATE)
.where(AUTOPAGERIZE_STATE.ID.eq(SINGLETON_ID))
.fetchSingle(this::mapState);
}
/**
* Locks the singleton state row with {@code FOR UPDATE}. Must be called inside an open
* transaction; otherwise the lock is released immediately.
*/
public AutoPagerizeActiveState lockActiveState() {
return dsl.select(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID, AUTOPAGERIZE_STATE.ACTIVATED_AT)
.from(AUTOPAGERIZE_STATE)
.where(AUTOPAGERIZE_STATE.ID.eq(SINGLETON_ID))
.forUpdate()
.fetchSingle(this::mapState);
}
/**
* Points the singleton at {@code datasetId}. Rejects unknown datasets with {@link
* IllegalArgumentException}. Does not open its own transaction.
*/
public void activateDataset(long datasetId) {
boolean exists =
dsl.fetchExists(
dsl.selectOne()
.from(AUTOPAGERIZE_DATASET)
.where(AUTOPAGERIZE_DATASET.ID.eq(datasetId)));
if (!exists) {
throw new IllegalArgumentException("AutoPagerize dataset does not exist: " + datasetId);
}
OffsetDateTime now = OffsetDateTime.now();
dsl.update(AUTOPAGERIZE_STATE)
.set(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID, datasetId)
.set(AUTOPAGERIZE_STATE.ACTIVATED_AT, now)
.where(AUTOPAGERIZE_STATE.ID.eq(SINGLETON_ID))
.execute();
}
/** Clears the active pointer (for tests / maintenance). Does not open its own transaction. */
public void clearActiveDataset() {
dsl.update(AUTOPAGERIZE_STATE)
.set(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID, (Long) null)
.set(AUTOPAGERIZE_STATE.ACTIVATED_AT, (OffsetDateTime) null)
.where(AUTOPAGERIZE_STATE.ID.eq(SINGLETON_ID))
.execute();
}
private AutoPagerizeActiveState mapState(Record record) {
return new AutoPagerizeActiveState(
record.get(AUTOPAGERIZE_STATE.ACTIVE_DATASET_ID),
record.get(AUTOPAGERIZE_STATE.ACTIVATED_AT));
}
}