288 lines
8.2 KiB
TypeScript
288 lines
8.2 KiB
TypeScript
import type { MarQSKeyProducer, MarQSKeyProducerEnv, QueueDescriptor } from "./types";
|
|
|
|
const constants = {
|
|
SHARED_QUEUE: "sharedQueue",
|
|
SHARED_WORKER_QUEUE: "sharedWorkerQueue",
|
|
CURRENT_CONCURRENCY_PART: "currentConcurrency",
|
|
CONCURRENCY_LIMIT_PART: "concurrency",
|
|
DISABLED_CONCURRENCY_LIMIT_PART: "disabledConcurrency",
|
|
ENV_PART: "env",
|
|
ORG_PART: "org",
|
|
QUEUE_PART: "queue",
|
|
CONCURRENCY_KEY_PART: "ck",
|
|
MESSAGE_PART: "message",
|
|
RESERVE_CONCURRENCY_PART: "reserveConcurrency",
|
|
} as const;
|
|
|
|
const ORG_REGEX = /org:([^:]+):/;
|
|
const ENV_REGEX = /env:([^:]+):/;
|
|
const QUEUE_REGEX = /queue:([^:]+)(?::|$)/;
|
|
const CONCURRENCY_KEY_REGEX = /ck:([^:]+)(?::|$)/;
|
|
|
|
export class MarQSShortKeyProducer implements MarQSKeyProducer {
|
|
constructor(private _prefix: string) {}
|
|
|
|
sharedQueueScanPattern() {
|
|
return `${this._prefix}*${constants.SHARED_QUEUE}`;
|
|
}
|
|
|
|
queueCurrentConcurrencyScanPattern() {
|
|
return `${this._prefix}${constants.ORG_PART}:*:${constants.ENV_PART}:*:queue:*:${constants.CURRENT_CONCURRENCY_PART}`;
|
|
}
|
|
|
|
stripKeyPrefix(key: string): string {
|
|
if (key.startsWith(this._prefix)) {
|
|
return key.slice(this._prefix.length);
|
|
}
|
|
|
|
return key;
|
|
}
|
|
|
|
queueConcurrencyLimitKey(env: MarQSKeyProducerEnv, queue: string) {
|
|
return [this.queueKey(env, queue), constants.CONCURRENCY_LIMIT_PART].join(":");
|
|
}
|
|
|
|
envConcurrencyLimitKey(envId: string): string;
|
|
envConcurrencyLimitKey(env: MarQSKeyProducerEnv): string;
|
|
envConcurrencyLimitKey(envOrId: MarQSKeyProducerEnv | string): string {
|
|
return [
|
|
this.envKeySection(typeof envOrId === "string" ? envOrId : envOrId.id),
|
|
constants.CONCURRENCY_LIMIT_PART,
|
|
].join(":");
|
|
}
|
|
|
|
queueKey(orgId: string, envId: string, queue: string, concurrencyKey?: string): string;
|
|
queueKey(env: MarQSKeyProducerEnv, queue: string, concurrencyKey?: string): string;
|
|
queueKey(
|
|
envOrOrgId: MarQSKeyProducerEnv | string,
|
|
queueOrEnvId: string,
|
|
queueOrConcurrencyKey: string,
|
|
concurrencyKeyOrPriority?: string | number
|
|
): string {
|
|
if (typeof envOrOrgId === "string") {
|
|
return [
|
|
this.orgKeySection(envOrOrgId),
|
|
this.envKeySection(queueOrEnvId),
|
|
this.queueSection(queueOrConcurrencyKey),
|
|
]
|
|
.concat(
|
|
typeof concurrencyKeyOrPriority === "string"
|
|
? this.concurrencyKeySection(concurrencyKeyOrPriority)
|
|
: []
|
|
)
|
|
.join(":");
|
|
} else {
|
|
return [
|
|
this.orgKeySection(envOrOrgId.organizationId),
|
|
this.envKeySection(envOrOrgId.id),
|
|
this.queueSection(queueOrEnvId),
|
|
]
|
|
.concat(queueOrConcurrencyKey ? this.concurrencyKeySection(queueOrConcurrencyKey) : [])
|
|
.join(":");
|
|
}
|
|
}
|
|
|
|
queueKeyFromQueue(queue: string): string {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return this.queueKey(
|
|
descriptor.organization,
|
|
descriptor.environment,
|
|
descriptor.name,
|
|
descriptor.concurrencyKey
|
|
);
|
|
}
|
|
|
|
envSharedQueueKey(env: MarQSKeyProducerEnv) {
|
|
if (env.type === "DEVELOPMENT") {
|
|
return [
|
|
this.orgKeySection(env.organizationId),
|
|
this.envKeySection(env.id),
|
|
constants.SHARED_QUEUE,
|
|
].join(":");
|
|
}
|
|
|
|
return this.sharedQueueKey();
|
|
}
|
|
|
|
sharedQueueKey(): string {
|
|
return constants.SHARED_QUEUE;
|
|
}
|
|
|
|
sharedWorkerQueueKey(): string {
|
|
return constants.SHARED_WORKER_QUEUE;
|
|
}
|
|
|
|
queueConcurrencyLimitKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return this.queueConcurrencyLimitKeyFromDescriptor(descriptor);
|
|
}
|
|
|
|
queueCurrentConcurrencyKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
return this.currentConcurrencyKeyFromDescriptor(descriptor);
|
|
}
|
|
|
|
queueReserveConcurrencyKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return this.queueReserveConcurrencyKeyFromDescriptor(descriptor);
|
|
}
|
|
|
|
queueCurrentConcurrencyKey(
|
|
env: MarQSKeyProducerEnv,
|
|
queue: string,
|
|
concurrencyKey?: string
|
|
): string {
|
|
return [this.queueKey(env, queue, concurrencyKey), constants.CURRENT_CONCURRENCY_PART].join(
|
|
":"
|
|
);
|
|
}
|
|
|
|
envConcurrencyLimitKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return `${constants.ENV_PART}:${descriptor.environment}:${constants.CONCURRENCY_LIMIT_PART}`;
|
|
}
|
|
|
|
envCurrentConcurrencyKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return `${constants.ENV_PART}:${descriptor.environment}:${constants.CURRENT_CONCURRENCY_PART}`;
|
|
}
|
|
|
|
envReserveConcurrencyKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return this.envReserveConcurrencyKey(descriptor.environment);
|
|
}
|
|
|
|
envReserveConcurrencyKey(envId: string): string {
|
|
return `${constants.ENV_PART}:${this.shortId(envId)}:${constants.RESERVE_CONCURRENCY_PART}`;
|
|
}
|
|
|
|
envCurrentConcurrencyKey(envId: string): string;
|
|
envCurrentConcurrencyKey(env: MarQSKeyProducerEnv): string;
|
|
envCurrentConcurrencyKey(envOrId: MarQSKeyProducerEnv | string): string {
|
|
return [
|
|
this.envKeySection(typeof envOrId === "string" ? envOrId : envOrId.id),
|
|
constants.CURRENT_CONCURRENCY_PART,
|
|
].join(":");
|
|
}
|
|
|
|
envQueueKeyFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return `${constants.ENV_PART}:${descriptor.environment}:${constants.QUEUE_PART}`;
|
|
}
|
|
|
|
envQueueKey(env: MarQSKeyProducerEnv): string {
|
|
return [constants.ENV_PART, this.shortId(env.id), constants.QUEUE_PART].join(":");
|
|
}
|
|
|
|
messageKey(messageId: string) {
|
|
return `${constants.MESSAGE_PART}:${messageId}`;
|
|
}
|
|
|
|
nackCounterKey(messageId: string): string {
|
|
return `${constants.MESSAGE_PART}:${messageId}:nacks`;
|
|
}
|
|
|
|
orgIdFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return descriptor.organization;
|
|
}
|
|
|
|
envIdFromQueue(queue: string) {
|
|
const descriptor = this.queueDescriptorFromQueue(queue);
|
|
|
|
return descriptor.environment;
|
|
}
|
|
|
|
queueDescriptorFromQueue(queue: string): QueueDescriptor {
|
|
const match = queue.match(QUEUE_REGEX);
|
|
|
|
if (!match) {
|
|
throw new Error(`Invalid queue: ${queue}, no queue name found`);
|
|
}
|
|
|
|
const [, queueName] = match;
|
|
|
|
const envMatch = queue.match(ENV_REGEX);
|
|
|
|
if (!envMatch) {
|
|
throw new Error(`Invalid queue: ${queue}, no environment found`);
|
|
}
|
|
|
|
const [, envId] = envMatch;
|
|
|
|
const orgMatch = queue.match(ORG_REGEX);
|
|
|
|
if (!orgMatch) {
|
|
throw new Error(`Invalid queue: ${queue}, no organization found`);
|
|
}
|
|
|
|
const [, orgId] = orgMatch;
|
|
|
|
const concurrencyKeyMatch = queue.match(CONCURRENCY_KEY_REGEX);
|
|
|
|
const concurrencyKey = concurrencyKeyMatch ? concurrencyKeyMatch[1] : undefined;
|
|
|
|
return {
|
|
name: queueName,
|
|
environment: envId,
|
|
organization: orgId,
|
|
concurrencyKey,
|
|
};
|
|
}
|
|
|
|
private shortId(id: string) {
|
|
// Return the last 12 characters of the id
|
|
return id.slice(-12);
|
|
}
|
|
|
|
private envKeySection(envId: string) {
|
|
return `${constants.ENV_PART}:${this.shortId(envId)}`;
|
|
}
|
|
|
|
private orgKeySection(orgId: string) {
|
|
return `${constants.ORG_PART}:${this.shortId(orgId)}`;
|
|
}
|
|
|
|
private queueSection(queue: string) {
|
|
return `${constants.QUEUE_PART}:${queue}`;
|
|
}
|
|
|
|
private concurrencyKeySection(concurrencyKey: string) {
|
|
return `${constants.CONCURRENCY_KEY_PART}:${concurrencyKey}`;
|
|
}
|
|
|
|
private currentConcurrencyKeyFromDescriptor(descriptor: QueueDescriptor) {
|
|
return [
|
|
this.queueKey(
|
|
descriptor.organization,
|
|
descriptor.environment,
|
|
descriptor.name,
|
|
descriptor.concurrencyKey
|
|
),
|
|
constants.CURRENT_CONCURRENCY_PART,
|
|
].join(":");
|
|
}
|
|
|
|
private queueReserveConcurrencyKeyFromDescriptor(descriptor: QueueDescriptor) {
|
|
return [
|
|
this.queueKey(descriptor.organization, descriptor.environment, descriptor.name),
|
|
constants.RESERVE_CONCURRENCY_PART,
|
|
].join(":");
|
|
}
|
|
|
|
private queueConcurrencyLimitKeyFromDescriptor(descriptor: QueueDescriptor) {
|
|
return [
|
|
this.queueKey(descriptor.organization, descriptor.environment, descriptor.name),
|
|
constants.CONCURRENCY_LIMIT_PART,
|
|
].join(":");
|
|
}
|
|
}
|