Skip to content
Merged
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
25 changes: 21 additions & 4 deletions src/base-command.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import {
} from "./services/config-manager.js";
import { ControlApi } from "./services/control-api.js";
import { CommandError } from "./errors/command-error.js";
import { getFriendlyAblyErrorHint } from "./utils/errors.js";
import { coreGlobalFlags } from "./flags.js";
import { InteractiveHelper } from "./services/interactive-helper.js";
import { BaseFlags, CommandConfig } from "./types/cli.js";
Expand Down Expand Up @@ -939,9 +940,10 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand {
logData,
);
} else if (level <= 1) {
// Standard Non-JSON: Log only SDK ERRORS (level <= 1) clearly
// Use a format similar to logCliEvent's non-JSON output
this.log(`${chalk.red.bold(`[AblySDK Error]`)} ${message}`);
// SDK errors are handled by setupChannelStateLogging() and fail()
// Only show raw SDK errors in verbose mode (handled above)
// In non-verbose mode, log to stderr for debugging without polluting stdout
this.logToStderr(`${chalk.red.bold(`[AblySDK Error]`)} ${message}`);
}
// If not verbose non-JSON and level > 1, suppress non-error SDK logs
}
Expand Down Expand Up @@ -1515,12 +1517,27 @@ export abstract class AblyBaseCommand extends InteractiveBaseCommand {
},
);

const friendlyHint = getFriendlyAblyErrorHint(
cmdError.code ??
(typeof cmdError.context.errorCode === "number"
? cmdError.context.errorCode
: undefined),
);

if (this.shouldOutputJson(flags)) {
this.log(this.formatJsonRecord("error", cmdError.toJsonData(), flags));
const jsonData = cmdError.toJsonData();
if (friendlyHint) {
jsonData.hint = friendlyHint;
}
this.log(this.formatJsonRecord("error", jsonData, flags));
this.exit(1);
}

let humanMessage = cmdError.message;
if (friendlyHint) {
humanMessage += `\n${friendlyHint}`;
}

const code = cmdError.code ?? cmdError.context.errorCode;
if (code !== undefined) {
const helpUrl = cmdError.context.helpUrl;
Expand Down
171 changes: 93 additions & 78 deletions src/commands/bench/publisher.ts
Original file line number Diff line number Diff line change
Expand Up @@ -313,58 +313,64 @@ export default class BenchPublisher extends AblyBaseCommand {
"waitingForSubscribers",
"Waiting for subscribers...",
);
await new Promise<void>((resolve) => {
const subscriberCheck = (member: Ably.PresenceMessage) => {
if (
member.data &&
typeof member.data === "object" &&
"role" in member.data &&
member.data.role === "subscriber"
) {
this.logCliEvent(
flags,
"benchmark",
"subscriberDetected",
`Subscriber detected: ${member.clientId}`,
{ clientId: member.clientId },
);
channel.presence.unsubscribe("enter", subscriberCheck);
resolve();
}
};

channel.presence.subscribe("enter", subscriberCheck);
channel.presence
.get()
.then((members) => {
const subscribers = members.filter(
(m) =>
m.data &&
typeof m.data === "object" &&
"role" in m.data &&
m.data.role === "subscriber",
);
if (subscribers.length > 0) {
this.logCliEvent(
flags,
"benchmark",
"subscribersFound",
`Found ${subscribers.length} subscribers already present`,
);
channel.presence.unsubscribe("enter", subscriberCheck);
resolve();
}
})
.catch((error) => {
this.logCliEvent(
flags,
"presence",
"getPresenceError",
`Error getting initial presence: ${errorMessage(error)}`,
);
// Continue waiting
});
let foundSubscriber: () => void;
const subscriberPromise = new Promise<void>((resolve) => {
foundSubscriber = resolve;
});

const subscriberCheck = (member: Ably.PresenceMessage) => {
if (
member.data &&
typeof member.data === "object" &&
"role" in member.data &&
member.data.role === "subscriber"
) {
this.logCliEvent(
flags,
"benchmark",
"subscriberDetected",
`Subscriber detected: ${member.clientId}`,
{ clientId: member.clientId },
);
channel.presence.unsubscribe("enter", subscriberCheck);
foundSubscriber();
}
};

await channel.presence.subscribe("enter", subscriberCheck);

// Check if subscribers are already present
try {
const members = await channel.presence.get();
const subscribers = members.filter(
(m) =>
m.data &&
typeof m.data === "object" &&
"role" in m.data &&
m.data.role === "subscriber",
);
if (subscribers.length > 0) {
this.logCliEvent(
flags,
"benchmark",
"subscribersFound",
`Found ${subscribers.length} subscribers already present`,
);
channel.presence.unsubscribe("enter", subscriberCheck);
// Already found, no need to wait
} else {
await subscriberPromise;
}
} catch (error) {
this.logCliEvent(
flags,
"presence",
"getPresenceError",
`Error getting initial presence: ${errorMessage(error)}`,
);
// Continue waiting for subscribe callback
await subscriberPromise;
}
} else {
const members = await channel.presence.get();
const subscribers = members.filter(
Expand Down Expand Up @@ -583,33 +589,42 @@ export default class BenchPublisher extends AblyBaseCommand {
testId,
};

channel.presence.subscribe("enter", (member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberEntered",
`Member entered presence: ${member.clientId}`,
{ clientId: member.clientId, data: member.data },
);
});
channel.presence.subscribe("leave", (member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberLeft",
`Member left presence: ${member.clientId}`,
{ clientId: member.clientId },
);
});
channel.presence.subscribe("update", (member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberUpdated",
`Member updated presence: ${member.clientId}`,
{ clientId: member.clientId, data: member.data },
);
});
await channel.presence.subscribe(
"enter",
(member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberEntered",
`Member entered presence: ${member.clientId}`,
{ clientId: member.clientId, data: member.data },
);
},
);
await channel.presence.subscribe(
"leave",
(member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberLeft",
`Member left presence: ${member.clientId}`,
{ clientId: member.clientId },
);
},
);
await channel.presence.subscribe(
"update",
(member: Ably.PresenceMessage) => {
this.logCliEvent(
flags,
"presence",
"memberUpdated",
`Member updated presence: ${member.clientId}`,
{ clientId: member.clientId, data: member.data },
);
},
);

this.logCliEvent(
flags,
Expand Down
Loading
Loading