mirror of
https://github.com/Kingsrook/qqq.git
synced 2025-07-18 13:10:44 +00:00
CE-938 Make session & user explicit fields, instead of packing into "holder"
This commit is contained in:
@ -51,8 +51,14 @@ public class ProcessLock extends QRecordEntity
|
|||||||
@QField(possibleValueSourceName = ProcessLockType.TABLE_NAME)
|
@QField(possibleValueSourceName = ProcessLockType.TABLE_NAME)
|
||||||
private Integer processLockTypeId;
|
private Integer processLockTypeId;
|
||||||
|
|
||||||
@QField(isRequired = true, maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
|
@QField(maxLength = 100, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
|
||||||
private String holder;
|
private String userId;
|
||||||
|
|
||||||
|
@QField(label = "Session UUID", maxLength = 36, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
|
||||||
|
private String sessionUUID;
|
||||||
|
|
||||||
|
@QField(maxLength = 250, valueTooLongBehavior = ValueTooLongBehavior.ERROR)
|
||||||
|
private String details;
|
||||||
|
|
||||||
@QField()
|
@QField()
|
||||||
private Instant checkInTimestamp;
|
private Instant checkInTimestamp;
|
||||||
@ -205,37 +211,6 @@ public class ProcessLock extends QRecordEntity
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Getter for holder
|
|
||||||
*******************************************************************************/
|
|
||||||
public String getHolder()
|
|
||||||
{
|
|
||||||
return (this.holder);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Setter for holder
|
|
||||||
*******************************************************************************/
|
|
||||||
public void setHolder(String holder)
|
|
||||||
{
|
|
||||||
this.holder = holder;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
|
||||||
** Fluent setter for holder
|
|
||||||
*******************************************************************************/
|
|
||||||
public ProcessLock withHolder(String holder)
|
|
||||||
{
|
|
||||||
this.holder = holder;
|
|
||||||
return (this);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
** Getter for checkInTimestamp
|
** Getter for checkInTimestamp
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@ -327,4 +302,97 @@ public class ProcessLock extends QRecordEntity
|
|||||||
return (this);
|
return (this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for userId
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getUserId()
|
||||||
|
{
|
||||||
|
return (this.userId);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for userId
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setUserId(String userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for userId
|
||||||
|
*******************************************************************************/
|
||||||
|
public ProcessLock withUserId(String userId)
|
||||||
|
{
|
||||||
|
this.userId = userId;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for sessionUUID
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getSessionUUID()
|
||||||
|
{
|
||||||
|
return (this.sessionUUID);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for sessionUUID
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setSessionUUID(String sessionUUID)
|
||||||
|
{
|
||||||
|
this.sessionUUID = sessionUUID;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for sessionUUID
|
||||||
|
*******************************************************************************/
|
||||||
|
public ProcessLock withSessionUUID(String sessionUUID)
|
||||||
|
{
|
||||||
|
this.sessionUUID = sessionUUID;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Getter for details
|
||||||
|
*******************************************************************************/
|
||||||
|
public String getDetails()
|
||||||
|
{
|
||||||
|
return (this.details);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Setter for details
|
||||||
|
*******************************************************************************/
|
||||||
|
public void setDetails(String details)
|
||||||
|
{
|
||||||
|
this.details = details;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/*******************************************************************************
|
||||||
|
** Fluent setter for details
|
||||||
|
*******************************************************************************/
|
||||||
|
public ProcessLock withDetails(String details)
|
||||||
|
{
|
||||||
|
this.details = details;
|
||||||
|
return (this);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -63,7 +63,7 @@ public class ProcessLockMetaDataProducer implements MetaDataProducerInterface<Me
|
|||||||
.withRecordLabelFormat("%s %s")
|
.withRecordLabelFormat("%s %s")
|
||||||
.withRecordLabelFields("processLockTypeId", "key")
|
.withRecordLabelFields("processLockTypeId", "key")
|
||||||
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "processLockTypeId", "key")))
|
.withSection(new QFieldSection("identity", new QIcon().withName("badge"), Tier.T1, List.of("id", "processLockTypeId", "key")))
|
||||||
.withSection(new QFieldSection("data", new QIcon().withName("text_snippet"), Tier.T2, List.of("holder", "checkInTimestamp", "expiresAtTimestamp")))
|
.withSection(new QFieldSection("data", new QIcon().withName("text_snippet"), Tier.T2, List.of("userId", "sessionUUID", "message", "checkInTimestamp", "expiresAtTimestamp")))
|
||||||
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")))
|
.withSection(new QFieldSection("dates", new QIcon().withName("calendar_month"), Tier.T3, List.of("createDate", "modifyDate")))
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -46,7 +46,6 @@ import com.kingsrook.qqq.backend.core.model.session.QSession;
|
|||||||
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
import com.kingsrook.qqq.backend.core.utils.CollectionUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.ObjectUtils;
|
import com.kingsrook.qqq.backend.core.utils.ObjectUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
import com.kingsrook.qqq.backend.core.utils.SleepUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.StringUtils;
|
|
||||||
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
import com.kingsrook.qqq.backend.core.utils.ValueUtils;
|
||||||
import com.kingsrook.qqq.backend.core.utils.memoization.Memoization;
|
import com.kingsrook.qqq.backend.core.utils.memoization.Memoization;
|
||||||
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
import static com.kingsrook.qqq.backend.core.logging.LogUtils.logPair;
|
||||||
@ -73,7 +72,7 @@ public class ProcessLockUtils
|
|||||||
/*******************************************************************************
|
/*******************************************************************************
|
||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
public static ProcessLock create(String key, String typeName, String holder) throws UnableToObtainProcessLockException, QException
|
public static ProcessLock create(String key, String typeName, String details) throws UnableToObtainProcessLockException, QException
|
||||||
{
|
{
|
||||||
ProcessLockType lockType = getProcessLockTypeByName(typeName);
|
ProcessLockType lockType = getProcessLockTypeByName(typeName);
|
||||||
if(lockType == null)
|
if(lockType == null)
|
||||||
@ -82,16 +81,14 @@ public class ProcessLockUtils
|
|||||||
}
|
}
|
||||||
|
|
||||||
QSession qSession = QContext.getQSession();
|
QSession qSession = QContext.getQSession();
|
||||||
holder = ObjectUtils.tryAndRequireNonNullElse(() -> qSession.getUser().getIdReference(), "anonymous")
|
|
||||||
+ "-"
|
|
||||||
+ ObjectUtils.tryAndRequireNonNullElse(() -> qSession.getUuid(), "no-session")
|
|
||||||
+ (StringUtils.hasContent(holder) ? ("-" + holder) : "");
|
|
||||||
|
|
||||||
Instant now = Instant.now();
|
Instant now = Instant.now();
|
||||||
ProcessLock processLock = new ProcessLock()
|
ProcessLock processLock = new ProcessLock()
|
||||||
.withKey(key)
|
.withKey(key)
|
||||||
.withProcessLockTypeId(lockType.getId())
|
.withProcessLockTypeId(lockType.getId())
|
||||||
.withHolder(holder)
|
.withSessionUUID(ObjectUtils.tryAndRequireNonNullElse(() -> qSession.getUuid(), null))
|
||||||
|
.withUserId(ObjectUtils.tryAndRequireNonNullElse(() -> qSession.getUser().getIdReference(), null))
|
||||||
|
.withDetails(details)
|
||||||
.withCheckInTimestamp(now);
|
.withCheckInTimestamp(now);
|
||||||
|
|
||||||
Integer defaultExpirationSeconds = lockType.getDefaultExpirationSeconds();
|
Integer defaultExpirationSeconds = lockType.getDefaultExpirationSeconds();
|
||||||
@ -126,7 +123,7 @@ public class ProcessLockUtils
|
|||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
Serializable id = existingLockRecord.getValue("id");
|
Serializable id = existingLockRecord.getValue("id");
|
||||||
LOG.info("Existing lock has expired - deleting it and trying again.", logPair("id", id),
|
LOG.info("Existing lock has expired - deleting it and trying again.", logPair("id", id),
|
||||||
logPair("key", key), logPair("type", typeName), logPair("holder", holder), logPair("expiresAtTimestamp", expiresAtTimestamp));
|
logPair("key", key), logPair("type", typeName), logPair("details", details), logPair("expiresAtTimestamp", expiresAtTimestamp));
|
||||||
new DeleteAction().execute(new DeleteInput(ProcessLock.TABLE_NAME).withPrimaryKey(id));
|
new DeleteAction().execute(new DeleteInput(ProcessLock.TABLE_NAME).withPrimaryKey(id));
|
||||||
insertOutputRecord = tryToInsert(processLock);
|
insertOutputRecord = tryToInsert(processLock);
|
||||||
}
|
}
|
||||||
@ -146,12 +143,12 @@ public class ProcessLockUtils
|
|||||||
// if at this point, we have errors on the last attempted insert, then give up //
|
// if at this point, we have errors on the last attempted insert, then give up //
|
||||||
/////////////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////////////
|
||||||
LOG.info("Errors in process lock record after attempted insert", logPair("errors", insertOutputRecord.getErrors()),
|
LOG.info("Errors in process lock record after attempted insert", logPair("errors", insertOutputRecord.getErrors()),
|
||||||
logPair("key", key), logPair("type", typeName), logPair("holder", holder));
|
logPair("key", key), logPair("type", typeName), logPair("details", details));
|
||||||
throw (new UnableToObtainProcessLockException("A Process Lock already exists for key [" + key + "] of type [" + typeName + "], " + existingLockDetails));
|
throw (new UnableToObtainProcessLockException("A Process Lock already exists for key [" + key + "] of type [" + typeName + "], " + existingLockDetails));
|
||||||
}
|
}
|
||||||
|
|
||||||
LOG.info("Created process lock", logPair("id", processLock.getId()),
|
LOG.info("Created process lock", logPair("id", processLock.getId()),
|
||||||
logPair("key", key), logPair("type", typeName), logPair("holder", holder), logPair("expiresAtTimestamp", processLock.getExpiresAtTimestamp()));
|
logPair("key", key), logPair("type", typeName), logPair("details", details), logPair("expiresAtTimestamp", processLock.getExpiresAtTimestamp()));
|
||||||
return new ProcessLock(insertOutputRecord);
|
return new ProcessLock(insertOutputRecord);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -42,6 +42,7 @@ import org.junit.jupiter.api.BeforeEach;
|
|||||||
import org.junit.jupiter.api.Test;
|
import org.junit.jupiter.api.Test;
|
||||||
import static org.assertj.core.api.Assertions.assertThat;
|
import static org.assertj.core.api.Assertions.assertThat;
|
||||||
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
import static org.assertj.core.api.Assertions.assertThatThrownBy;
|
||||||
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
import static org.junit.jupiter.api.Assertions.assertNotEquals;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
import static org.junit.jupiter.api.Assertions.assertNotNull;
|
||||||
import static org.junit.jupiter.api.Assertions.assertNull;
|
import static org.junit.jupiter.api.Assertions.assertNull;
|
||||||
@ -125,7 +126,7 @@ class ProcessLockUtilsTest extends BaseTest
|
|||||||
//////////////////////
|
//////////////////////
|
||||||
processLock = ProcessLockUtils.create("1", "typeA", "you");
|
processLock = ProcessLockUtils.create("1", "typeA", "you");
|
||||||
assertNotNull(processLock.getId());
|
assertNotNull(processLock.getId());
|
||||||
assertThat(processLock.getHolder()).endsWith("you");
|
assertEquals("you", processLock.getDetails());
|
||||||
|
|
||||||
assertThatThrownBy(() -> ProcessLockUtils.create("1", "notAType", "you"))
|
assertThatThrownBy(() -> ProcessLockUtils.create("1", "notAType", "you"))
|
||||||
.isInstanceOf(QException.class)
|
.isInstanceOf(QException.class)
|
||||||
@ -150,7 +151,7 @@ class ProcessLockUtilsTest extends BaseTest
|
|||||||
/////////////////////////////////////////////////////////////////////////
|
/////////////////////////////////////////////////////////////////////////
|
||||||
processLock = ProcessLockUtils.create("1", "typeB", "you", Duration.of(1, ChronoUnit.SECONDS), Duration.of(3, ChronoUnit.SECONDS));
|
processLock = ProcessLockUtils.create("1", "typeB", "you", Duration.of(1, ChronoUnit.SECONDS), Duration.of(3, ChronoUnit.SECONDS));
|
||||||
assertNotNull(processLock.getId());
|
assertNotNull(processLock.getId());
|
||||||
assertThat(processLock.getHolder()).endsWith("you");
|
assertThat(processLock.getDetails()).endsWith("you");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -220,26 +221,46 @@ class ProcessLockUtilsTest extends BaseTest
|
|||||||
**
|
**
|
||||||
*******************************************************************************/
|
*******************************************************************************/
|
||||||
@Test
|
@Test
|
||||||
void testHolders() throws QException
|
void testUserAndSessionNullness() throws QException
|
||||||
|
{
|
||||||
{
|
{
|
||||||
QContext.getQSession().setUser(new QUser().withIdReference("me"));
|
QContext.getQSession().setUser(new QUser().withIdReference("me"));
|
||||||
assertThat(ProcessLockUtils.create("1", "typeA", null).getHolder())
|
ProcessLock processLock = ProcessLockUtils.create("1", "typeA", null);
|
||||||
.isEqualTo("me-" + QContext.getQSession().getUuid());
|
assertNull(processLock.getDetails());
|
||||||
|
assertEquals("me", processLock.getUserId());
|
||||||
|
assertEquals(QContext.getQSession().getUuid(), processLock.getSessionUUID());
|
||||||
|
}
|
||||||
|
|
||||||
assertThat(ProcessLockUtils.create("2", "typeA", "foo").getHolder())
|
{
|
||||||
.isEqualTo("me-" + QContext.getQSession().getUuid() + "-foo");
|
ProcessLock processLock = ProcessLockUtils.create("2", "typeA", "foo");
|
||||||
|
assertEquals("foo", processLock.getDetails());
|
||||||
|
assertEquals("me", processLock.getUserId());
|
||||||
|
assertEquals(QContext.getQSession().getUuid(), processLock.getSessionUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
QContext.getQSession().setUser(null);
|
QContext.getQSession().setUser(null);
|
||||||
assertThat(ProcessLockUtils.create("3", "typeA", "bar").getHolder())
|
ProcessLock processLock = ProcessLockUtils.create("3", "typeA", "bar");
|
||||||
.isEqualTo("anonymous-" + QContext.getQSession().getUuid() + "-bar");
|
assertEquals("bar", processLock.getDetails());
|
||||||
|
assertNull(processLock.getUserId());
|
||||||
|
assertEquals(QContext.getQSession().getUuid(), processLock.getSessionUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
QContext.getQSession().setUuid(null);
|
QContext.getQSession().setUuid(null);
|
||||||
assertThat(ProcessLockUtils.create("4", "typeA", "baz").getHolder())
|
ProcessLock processLock = ProcessLockUtils.create("4", "typeA", "baz");
|
||||||
.isEqualTo("anonymous-no-session-baz");
|
assertEquals("baz", processLock.getDetails());
|
||||||
|
assertNull(processLock.getUserId());
|
||||||
|
assertNull(processLock.getSessionUUID());
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
QContext.getQSession().setUuid(null);
|
QContext.getQSession().setUuid(null);
|
||||||
assertThat(ProcessLockUtils.create("5", "typeA", "").getHolder())
|
ProcessLock processLock = ProcessLockUtils.create("5", "typeA", "");
|
||||||
.isEqualTo("anonymous-no-session");
|
assertEquals("", processLock.getDetails());
|
||||||
|
assertNull(processLock.getUserId());
|
||||||
|
assertNull(processLock.getSessionUUID());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
Reference in New Issue
Block a user