Skip to content

Commit

Permalink
breaking(services): the queue property now if set to an empty string …
Browse files Browse the repository at this point in the history
…means that the service/endpoint/group will not be in a queue. Clients that specifically assign queue names should experience no changes. And clients that didn't specify a value for the property (so the property was undefined) should also not experience a change and should see their service/endpoint/group use the `q` group. If explicetly set to an empty string ``, the service will NOT be part of a queue. (#114)

breaking(services): the metadata configuration specified when creating the service is now stored read-only, any type of edit on the internal copy will result in a `TypeError` as the metdata object is frozen.

Signed-off-by: Alberto Ricart <[email protected]>
  • Loading branch information
aricart authored Nov 5, 2024
1 parent 5ab062e commit 69eb332
Show file tree
Hide file tree
Showing 3 changed files with 79 additions and 8 deletions.
16 changes: 12 additions & 4 deletions services/src/service.ts
Original file line number Diff line number Diff line change
Expand Up @@ -162,7 +162,7 @@ export class ServiceGroupImpl implements ServiceGroup {
} else if (parent instanceof ServiceGroupImpl) {
const sg = parent as ServiceGroupImpl;
this.srv = sg.srv;
if (queue === "" && sg.queue !== "") {
if (queue === undefined) {
queue = sg.queue;
}
root = sg.subject;
Expand Down Expand Up @@ -198,7 +198,10 @@ export class ServiceGroupImpl implements ServiceGroup {
return this.srv._addEndpoint(ne);
}

addGroup(name = "", queue = ""): ServiceGroup {
addGroup(name = "", queue?: string): ServiceGroup {
if (queue === undefined) {
queue = this.queue;
}
return new ServiceGroupImpl(this, name, queue);
}
}
Expand Down Expand Up @@ -286,13 +289,18 @@ export class ServiceImpl implements Service {
) {
this.nc = nc;
this.config = Object.assign({}, config);
if (!this.config.queue) {
if (this.config.queue === undefined) {
this.config.queue = "q";
}

// don't allow changing metadata
config.metadata = Object.freeze(config.metadata || {});

// this will throw if no name
validateName("name", this.config.name);
validateName("queue", this.config.queue);
if (this.config.queue) {
validateName("queue", this.config.queue);
}

// this will throw if not semver
parseSemVer(this.config.version);
Expand Down
13 changes: 9 additions & 4 deletions services/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,8 @@ export type Endpoint = {
metadata?: Record<string, string>;
/**
* Optional queue group to run this particular endpoint in. The service's configuration
* queue configuration will be used. See {@link ServiceConfig}.
* queue configuration will be used. See {@link ServiceConfig}. Note that if the queue
* is set to an empty string, it will not be run in a queue.
*/
queue?: string;
};
Expand Down Expand Up @@ -81,6 +82,8 @@ export interface ServiceGroup {
* without requiring editing of the service.
* Note that an optional queue can be specified, all endpoints added to
* the group, will use the specified queue unless the endpoint overrides it.
* When not set, it uses the parent group configuration. An empty string
* means no queue.
* see {@link EndpointOptions} and {@link ServiceConfig}.
* @param subject
* @param queue
Expand Down Expand Up @@ -208,9 +211,11 @@ export type ServiceConfig = {
*/
metadata?: Record<string, string>;
/**
* Optional queue group to run the service in. By default,
* then queue name is "q". Note that this configuration will
* be the default for all endpoints and groups.
* Optional queue group to run the service in. If not set, default,
* is set to "q". Note that this configuration will
* be the default for all endpoints and groups. If set to an empty
* string, the service subscription will NOT have queue, and will
* not be run in a queue.
*/
queue?: string;
};
Expand Down
58 changes: 58 additions & 0 deletions services/tests/service_test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1047,3 +1047,61 @@ Deno.test("service - endpoint default queue group", async () => {

await cleanup(ns, nc);
});

Deno.test("service - endpoint no queue group", async () => {
const { ns, nc } = await setup();

const svc = new Svc(nc);
const srv = await svc.add({
name: "example",
version: "0.0.1",
metadata: { service: "1" },
// no queue
queue: "",
}) as ServiceImpl;

// svc config doesn't specify a queue group so we expect q
srv.addEndpoint("a");
checkQueueGroup(srv, "a", "");

// we add another group, no queue
const dg = srv.addGroup("G");
dg.addEndpoint("a");
checkQueueGroup(srv, "G.a", "");

// the above have no queue, no override, and set a queue
const g = srv.addGroup("g", "qq");
g.addEndpoint("a");
checkQueueGroup(srv, "g.a", "qq");
// override
g.addEndpoint("b", { queue: "bb" });
checkQueueGroup(srv, "g.b", "bb");
// add a subgroup without, should inherit
const g2 = g.addGroup("g");
g2.addEndpoint("a");
checkQueueGroup(srv, "g.g.a", "qq");

await cleanup(ns, nc);
});

Deno.test("service - metadata is not editable", async () => {
const { ns, nc } = await setup();

const svc = new Svc(nc);
const srv = await svc.add({
name: "example",
version: "0.0.1",
metadata: { service: "1", hello: "world" },
queue: "",
}) as ServiceImpl;

assertThrows(
() => {
srv.config.metadata!.hello = "hello";
},
TypeError,
"Cannot assign to read only property",
);

await cleanup(ns, nc);
});

0 comments on commit 69eb332

Please sign in to comment.