Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/wet-grapes-vanish.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"wrangler": minor
---

feat: Add a new update command for Queues and a message-retention-period-secs option

A new queues update command has been added to support selectively updating queues settings. message-retention-period-secs has been added as an option in both the queues create and update commands
278 changes: 276 additions & 2 deletions packages/wrangler/src/__tests__/queues.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ describe("wrangler", () => {
COMMANDS
wrangler queues list List Queues
wrangler queues create <name> Create a Queue
wrangler queues update <name> Update a Queue
wrangler queues delete <name> Delete a Queue
wrangler queues consumer Configure Queue consumers

Expand Down Expand Up @@ -196,7 +197,9 @@ describe("wrangler", () => {
describe("create", () => {
function mockCreateRequest(
queueName: string,
queueSettings: { delivery_delay?: number } | undefined = undefined
queueSettings:
| { delivery_delay?: number; message_retention_period?: number }
| undefined = undefined
) {
const requests = { count: 0 };

Expand All @@ -210,6 +213,7 @@ describe("wrangler", () => {
queue_name: string;
settings: {
delivery_delay: number;
message_retention_period: number;
};
};
expect(body.queue_name).toEqual(queueName);
Expand Down Expand Up @@ -250,7 +254,8 @@ describe("wrangler", () => {
-v, --version Show version number [boolean]

OPTIONS
--delivery-delay-secs How long a published message should be delayed for, in seconds. Must be a positive integer [number]"
--delivery-delay-secs How long a published message should be delayed for, in seconds. Must be between 0 and 42300 [number]
--message-retention-period-secs How long to retain a message in the queue, in seconds. Must be between 60 and 1209600 [number]"
`);
});

Expand Down Expand Up @@ -327,6 +332,275 @@ describe("wrangler", () => {

expect(requests.count).toEqual(0);
});

it("should show an error when invalid delivery delay is set", async () => {
const requests = mockCreateRequest("testQueue", { delivery_delay: 10 });
await expect(
runWrangler("queues create testQueue --delivery-delay-secs=99999")
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Invalid --delivery-delay-secs value: 99999. Must be between 0 and 42300]`
);

expect(requests.count).toEqual(0);
});

it("should send queue settings with message retention period", async () => {
const requests = mockCreateRequest("testQueue", {
message_retention_period: 100,
});
await runWrangler(
"queues create testQueue --message-retention-period-secs=100"
);
expect(std.out).toMatchInlineSnapshot(`
"Creating queue testQueue.
Created queue testQueue."
`);
expect(requests.count).toEqual(1);
});

it("should show an error when two message retention periods are set", async () => {
const requests = mockCreateRequest("testQueue", {
message_retention_period: 60,
});

await expect(
runWrangler(
"queues create testQueue --message-retention-period-secs=70 --message-retention-period-secs=80"
)
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Cannot specify --message-retention-period-secs multiple times]`
);

expect(requests.count).toEqual(0);
});

it("should show an error when invalid message retention period is set", async () => {
const requests = mockCreateRequest("testQueue", {
message_retention_period: 100,
});
await expect(
runWrangler(
"queues create testQueue --message-retention-period-secs=0"
)
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Invalid --message-retention-period-secs value: 0. Must be between 60 and 1209600]`
);

expect(requests.count).toEqual(0);
});
});

describe("update", () => {
function mockUpdateRequest(
queueName: string,
queueSettings:
| { delivery_delay?: number; message_retention_period?: number }
| undefined = undefined
) {
const requests = { count: 0 };

msw.use(
http.put(
"*/accounts/:accountId/queues/:queueId",
async ({ request }) => {
requests.count += 1;

const body = (await request.json()) as {
queue_name: string;
settings: {
delivery_delay: number;
message_retention_period: number;
};
};
expect(body.queue_name).toEqual(queueName);
expect(body.settings).toEqual(queueSettings);
return HttpResponse.json({
success: true,
errors: [],
messages: [],
result: {
queue_name: queueName,
created_on: "01-01-2001",
modified_on: "01-01-2001",
},
});
},
{ once: true }
)
);
return requests;
}
function mockGetQueueRequest(
queueName: string,
queueSettings: {
delivery_delay: number;
message_retention_period: number;
}
) {
const requests = { count: 0 };
msw.use(
http.get(
"*/accounts/:accountId/queues?*",
async () => {
requests.count += 1;
return HttpResponse.json({
success: true,
errors: [],
messages: [],
result: [
{
queue_name: queueName,
created_on: "",
producers: [],
consumers: [],
producers_total_count: 1,
consumers_total_count: 0,
modified_on: "",
queue_id: "queueId",
settings: {
delivery_delay: queueSettings.delivery_delay,
message_retention_period:
queueSettings.message_retention_period,
},
},
],
});
},
{ once: true }
)
);
return requests;
}

it("should show the correct help text", async () => {
await runWrangler("queues update --help");
expect(std.err).toMatchInlineSnapshot(`""`);
expect(std.out).toMatchInlineSnapshot(`
"wrangler queues update <name>

Update a Queue

POSITIONALS
name The name of the queue [string] [required]

GLOBAL FLAGS
-j, --experimental-json-config Experimental: support wrangler.json [boolean]
-c, --config Path to .toml configuration file [string]
-e, --env Environment to use for operations and .env files [string]
-h, --help Show help [boolean]
-v, --version Show version number [boolean]

OPTIONS
--delivery-delay-secs How long a published message should be delayed for, in seconds. Must be between 0 and 42300 [number]
--message-retention-period-secs How long to retain a message in the queue, in seconds. Must be between 60 and 1209600 [number]"
`);
});

it("should update a queue with new message retention period and preserve old delivery delay", async () => {
const getrequests = mockGetQueueRequest("testQueue", {
delivery_delay: 10,
message_retention_period: 100,
});

//update queue with new message retention period
const requests = mockUpdateRequest("testQueue", {
delivery_delay: 10,
message_retention_period: 400,
});
await runWrangler(
"queues update testQueue --message-retention-period-secs=400"
);

expect(requests.count).toEqual(1);
expect(getrequests.count).toEqual(1);

expect(std.out).toMatchInlineSnapshot(`
"Updating queue testQueue.
Updated queue testQueue."
`);
});

it("should show an error when two message retention periods are set", async () => {
const requests = mockUpdateRequest("testQueue", {
message_retention_period: 60,
});

mockGetQueueRequest("testQueue", {
delivery_delay: 0,
message_retention_period: 100,
});

await expect(
runWrangler(
"queues update testQueue --message-retention-period-secs=70 --message-retention-period-secs=80"
)
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Cannot specify --message-retention-period-secs multiple times]`
);

expect(requests.count).toEqual(0);
});

it("should show an error when two delivery delays are set", async () => {
const requests = mockUpdateRequest("testQueue", {
delivery_delay: 10,
});

mockGetQueueRequest("testQueue", {
delivery_delay: 0,
message_retention_period: 100,
});

await expect(
runWrangler(
"queues update testQueue --delivery-delay-secs=5 --delivery-delay-secs=10"
)
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Cannot specify --delivery-delay-secs multiple times]`
);

expect(requests.count).toEqual(0);
});

it("should show an error when invalid delivery delay is set", async () => {
const requests = mockUpdateRequest("testQueue", {
delivery_delay: 10,
});

mockGetQueueRequest("testQueue", {
delivery_delay: 0,
message_retention_period: 100,
});

await expect(
runWrangler("queues update testQueue --delivery-delay-secs=99999")
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Invalid --delivery-delay-secs value: 99999. Must be between 0 and 42300]`
);

expect(requests.count).toEqual(0);
});

it("should show an error when invalid message retention period is set", async () => {
const requests = mockUpdateRequest("testQueue", {
message_retention_period: 100,
});

mockGetQueueRequest("testQueue", {
delivery_delay: 0,
message_retention_period: 100,
});

await expect(
runWrangler(
"queues update testQueue --message-retention-period-secs=0"
)
).rejects.toThrowErrorMatchingInlineSnapshot(
`[Error: Invalid --message-retention-period-secs value: 0. Must be between 60 and 1209600]`
);

expect(requests.count).toEqual(0);
});
});

describe("delete", () => {
Expand Down
49 changes: 45 additions & 4 deletions packages/wrangler/src/queues/cli/commands/create.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,12 @@ import { readConfig } from "../../../config";
import { CommandLineArgsError } from "../../../index";
import { logger } from "../../../logger";
import { createQueue } from "../../client";
import {
MAX_DELIVERY_DELAY_SECS,
MAX_MESSAGE_RETENTION_PERIOD_SECS,
MIN_DELIVERY_DELAY_SECS,
MIN_MESSAGE_RETENTION_PERIOD_SECS,
} from "../../constants";
import { handleFetchError } from "../../utils";
import type {
CommonYargsArgv,
Expand All @@ -20,7 +26,12 @@ export function options(yargs: CommonYargsArgv) {
"delivery-delay-secs": {
type: "number",
describe:
"How long a published message should be delayed for, in seconds. Must be a positive integer",
"How long a published message should be delayed for, in seconds. Must be between 0 and 42300",
},
"message-retention-period-secs": {
type: "number",
describe:
"How long to retain a message in the queue, in seconds. Must be between 60 and 1209600",
},
});
}
Expand All @@ -38,10 +49,40 @@ function createBody(
);
}

if (Array.isArray(args.messageRetentionPeriodSecs)) {
throw new CommandLineArgsError(
"Cannot specify --message-retention-period-secs multiple times"
);
}

body.settings = {};

if (args.deliveryDelaySecs != undefined) {
body.settings = {
delivery_delay: args.deliveryDelaySecs,
};
if (
args.deliveryDelaySecs < MIN_DELIVERY_DELAY_SECS ||
args.deliveryDelaySecs > MAX_DELIVERY_DELAY_SECS
) {
throw new CommandLineArgsError(
`Invalid --delivery-delay-secs value: ${args.deliveryDelaySecs}. Must be between ${MIN_DELIVERY_DELAY_SECS} and ${MAX_DELIVERY_DELAY_SECS}`
);
}
body.settings.delivery_delay = args.deliveryDelaySecs;
}

if (args.messageRetentionPeriodSecs != undefined) {
if (
args.messageRetentionPeriodSecs < MIN_MESSAGE_RETENTION_PERIOD_SECS ||
args.messageRetentionPeriodSecs > MAX_MESSAGE_RETENTION_PERIOD_SECS
) {
throw new CommandLineArgsError(
`Invalid --message-retention-period-secs value: ${args.messageRetentionPeriodSecs}. Must be between ${MIN_MESSAGE_RETENTION_PERIOD_SECS} and ${MAX_MESSAGE_RETENTION_PERIOD_SECS}`
);
}
body.settings.message_retention_period = args.messageRetentionPeriodSecs;
}

if (Object.keys(body.settings).length === 0) {
body.settings = undefined;
}

return body;
Expand Down
Loading