redis-smq
Version:
A high-performance, reliable, and scalable message queue for Node.js.
161 lines • 5.91 kB
JavaScript
import { CronExpressionParser } from 'cron-parser';
import { MessageDestinationQueueAlreadySetError, MessageDestinationQueueRequiredError, } from '../errors/index.js';
import { MessageState } from './message-state.js';
import { EMessagePropertyStatus, } from './types/index.js';
export class MessageEnvelope {
messageState;
status = EMessagePropertyStatus.NEW;
destinationQueue = null;
consumerGroupId = null;
producibleMessage;
constructor(producibleMessage, messageState = null, status = EMessagePropertyStatus.NEW) {
this.producibleMessage = producibleMessage;
if (messageState)
this.messageState = messageState;
else {
this.messageState = new MessageState();
const scheduledDelay = this.producibleMessage.getScheduledDelay();
if (scheduledDelay)
this.messageState.setEffectiveScheduledDelay(scheduledDelay);
}
this.status = status;
}
getMessageState() {
return this.messageState;
}
setMessageState(m) {
this.messageState = m;
return this;
}
getId() {
return this.messageState.getId();
}
getSetExpired() {
return this.getMessageState().getSetExpired(this.producibleMessage.getTTL(), this.producibleMessage.getCreatedAt());
}
getStatus() {
return this.status;
}
setDestinationQueue(queue) {
if (this.destinationQueue !== null) {
throw new MessageDestinationQueueAlreadySetError();
}
this.destinationQueue = queue;
return this;
}
setStatus(s) {
this.status = s;
return this;
}
getDestinationQueue() {
if (!this.destinationQueue) {
throw new MessageDestinationQueueRequiredError();
}
return this.destinationQueue;
}
hasNextDelay() {
return this.messageState.hasDelay();
}
getNextScheduledTimestamp() {
if (!this.isSchedulable()) {
return 0;
}
const messageState = this.getMessageState();
const now = Date.now();
const delay = messageState.getSetEffectiveScheduledDelay();
if (delay) {
return now + delay;
}
const producibleMessage = this.producibleMessage;
const cronExpression = producibleMessage.getScheduledCRON();
const repeatLimit = producibleMessage.getScheduledRepeat();
if (!cronExpression && !repeatLimit) {
return 0;
}
const cronTimestamp = cronExpression
? CronExpressionParser.parse(cronExpression).next().getTime()
: 0;
let repeatTimestamp = 0;
const currentRepeatCount = messageState.getScheduledRepeatCount();
if (currentRepeatCount < repeatLimit) {
const isCronFired = messageState.isScheduledCronFired();
if (!cronExpression || isCronFired) {
const repeatPeriod = producibleMessage.getScheduledRepeatPeriod() ?? 0;
if (cronExpression) {
repeatTimestamp = now + repeatPeriod;
}
else {
repeatTimestamp = currentRepeatCount > 0 ? now + repeatPeriod : now;
}
}
}
if (cronTimestamp && repeatTimestamp) {
if (repeatTimestamp < cronTimestamp) {
messageState.incrScheduledRepeatCount();
return repeatTimestamp;
}
messageState.resetScheduledRepeatCount();
messageState.setScheduledCronFired(true);
return cronTimestamp;
}
if (cronTimestamp) {
messageState.resetScheduledRepeatCount();
messageState.setScheduledCronFired(true);
return cronTimestamp;
}
if (repeatTimestamp) {
messageState.incrScheduledRepeatCount();
return repeatTimestamp;
}
return 0;
}
toString() {
return JSON.stringify(this);
}
setConsumerGroupId(consumerGroupId) {
this.consumerGroupId = consumerGroupId;
return this;
}
getConsumerGroupId() {
return this.consumerGroupId;
}
toJSON() {
return {
createdAt: this.producibleMessage.getCreatedAt(),
ttl: this.producibleMessage.getTTL(),
retryThreshold: this.producibleMessage.getRetryThreshold(),
retryDelay: this.producibleMessage.getRetryDelay(),
consumeTimeout: this.producibleMessage.getConsumeTimeout(),
body: this.producibleMessage.getBody(),
priority: this.producibleMessage.getPriority(),
scheduledCron: this.producibleMessage.getScheduledCRON(),
scheduledDelay: this.producibleMessage.getScheduledDelay(),
scheduledRepeatPeriod: this.producibleMessage.getScheduledRepeatPeriod(),
scheduledRepeat: this.producibleMessage.getScheduledRepeat(),
exchange: this.producibleMessage.getExchange(),
queue: this.producibleMessage.getQueue(),
destinationQueue: this.getDestinationQueue(),
consumerGroupId: this.getConsumerGroupId(),
};
}
transfer() {
return {
...this.toJSON(),
id: this.getId(),
messageState: this.getMessageState().toJSON(),
status: this.getStatus(),
};
}
hasRetryThresholdExceeded() {
const threshold = this.producibleMessage.getRetryThreshold();
return this.messageState.getAttempts() >= threshold;
}
isSchedulable() {
return this.hasNextDelay() || this.isPeriodic();
}
isPeriodic() {
return (this.producibleMessage.getScheduledCRON() !== null ||
this.producibleMessage.getScheduledRepeat() > 0);
}
}
//# sourceMappingURL=message-envelope.js.map