mirror of
https://github.com/PHIDIAS0303/ExpCluster.git
synced 2026-11-11 15:54:52 +09:00
Replace RequestError with the HTTP-style error classes
clusterio#999 removed RequestError. Handlers now throw NotFoundError, ValidationError, ConflictError or UnavailableError, and exp_auto_restart treats any ClientError from the host as a final refusal. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
afc1d35668
commit
389004d652
8 files changed
+32
-32
No files matched your search
@@ -197,7 +197,7 @@ export class AutoRestart {
|
|||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
this.pending.delete(host.id);
|
this.pending.delete(host.id);
|
||||||
// The host refusing is final for this process, anything else is retried
|
// The host refusing is final for this process, anything else is retried
|
||||||
if (!(err instanceof lib.RequestError)) {
|
if (!(err instanceof lib.ClientError)) {
|
||||||
this.requested.delete(host.id);
|
this.requested.delete(host.id);
|
||||||
}
|
}
|
||||||
this.logger.error(`Failed to restart host ${host.name}: ${err.message}`);
|
this.logger.error(`Failed to restart host ${host.name}: ${err.message}`);
|
||||||
|
|||||||
@@ -219,7 +219,7 @@ t.test("class AutoRestart", t2 => {
|
|||||||
addInstance(controller, 10, 1);
|
addInstance(controller, 10, 1);
|
||||||
addSystem(controller, 1);
|
addSystem(controller, 1);
|
||||||
|
|
||||||
controller.sendTo = async () => { throw new lib.RequestError("Cannot restart"); };
|
controller.sendTo = async () => { throw new lib.ConflictError("Cannot restart"); };
|
||||||
await plugin.check(now);
|
await plugin.check(now);
|
||||||
await plugin.check(now + 10_000);
|
await plugin.check(now + 10_000);
|
||||||
t3.strictSame(logs.filter(([level]) => level === "error").length, 1, "a refusal is logged once");
|
t3.strictSame(logs.filter(([level]) => level === "error").length, 1, "a refusal is logged once");
|
||||||
|
|||||||
@@ -385,7 +385,7 @@ export class ControllerPlugin {
|
|||||||
const entry = this.codes.get(code);
|
const entry = this.codes.get(code);
|
||||||
const session = entry ? this.sessions.get(entry.sessionId) : undefined;
|
const session = entry ? this.sessions.get(entry.sessionId) : undefined;
|
||||||
if (!entry || !session || entry.expiresMs < Date.now()) {
|
if (!entry || !session || entry.expiresMs < Date.now()) {
|
||||||
throw new lib.RequestError(
|
throw new lib.ValidationError(
|
||||||
`This code is invalid or has expired, get a new one from ${this.controller.getControllerUrl()}`
|
`This code is invalid or has expired, get a new one from ${this.controller.getControllerUrl()}`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -403,7 +403,7 @@ export class ControllerPlugin {
|
|||||||
const alreadyLinked = existing?.factorioNames.some(linked => linked.toLowerCase() === name);
|
const alreadyLinked = existing?.factorioNames.some(linked => linked.toLowerCase() === name);
|
||||||
const maxAccounts = this.controller.config.get("exp_discord_auth.max_accounts");
|
const maxAccounts = this.controller.config.get("exp_discord_auth.max_accounts");
|
||||||
if (!alreadyLinked && (existing?.factorioNames.length ?? 0) >= maxAccounts) {
|
if (!alreadyLinked && (existing?.factorioNames.length ?? 0) >= maxAccounts) {
|
||||||
throw new lib.RequestError(
|
throw new lib.ConflictError(
|
||||||
`${discordUser.name} already has ${maxAccounts} Factorio accounts linked, unlink one first`
|
`${discordUser.name} already has ${maxAccounts} Factorio accounts linked, unlink one first`
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-11
@@ -233,7 +233,7 @@ export class ControllerPlugin {
|
|||||||
|
|
||||||
async handleGroupCreateRequest(request: messages.GroupCreateRequest) {
|
async handleGroupCreateRequest(request: messages.GroupCreateRequest) {
|
||||||
if ([...this.groups.values()].some(g => g.name === request.name)) {
|
if ([...this.groups.values()].some(g => g.name === request.name)) {
|
||||||
throw new lib.RequestError(`Group with name '${request.name}' already exists`);
|
throw new lib.ConflictError(`Group with name '${request.name}' already exists`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = Math.random() * 2**31 | 0;
|
let id = Math.random() * 2**31 | 0;
|
||||||
@@ -249,7 +249,7 @@ export class ControllerPlugin {
|
|||||||
async handleGroupUpdateRequest(request: messages.GroupUpdateRequest) {
|
async handleGroupUpdateRequest(request: messages.GroupUpdateRequest) {
|
||||||
const group = request.group;
|
const group = request.group;
|
||||||
if (group.id === undefined || !this.groups.has(group.id)) {
|
if (group.id === undefined || !this.groups.has(group.id)) {
|
||||||
throw new lib.RequestError(`Group with ID ${group.id} does not exist`);
|
throw new lib.NotFoundError(`Group with ID ${group.id} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.groups.set(group);
|
this.groups.set(group);
|
||||||
@@ -260,7 +260,7 @@ export class ControllerPlugin {
|
|||||||
|
|
||||||
const group = this.groups.getMutable(groupId);
|
const group = this.groups.getMutable(groupId);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw new lib.RequestError(`Group with ID ${groupId} does not exist`);
|
throw new lib.NotFoundError(`Group with ID ${groupId} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.groups.delete(group);
|
this.groups.delete(group);
|
||||||
@@ -269,7 +269,7 @@ export class ControllerPlugin {
|
|||||||
async handleGroupGetRequest(request: messages.GroupGetRequest) {
|
async handleGroupGetRequest(request: messages.GroupGetRequest) {
|
||||||
const group = this.groups.get(request.groupId);
|
const group = this.groups.get(request.groupId);
|
||||||
if (!group) {
|
if (!group) {
|
||||||
throw new lib.RequestError(`Group with ID ${request.groupId} does not exist`);
|
throw new lib.NotFoundError(`Group with ID ${request.groupId} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return group;
|
return group;
|
||||||
@@ -286,7 +286,7 @@ export class ControllerPlugin {
|
|||||||
async handleAssignmentCreateRequest(request: messages.AssignmentCreateRequest) {
|
async handleAssignmentCreateRequest(request: messages.AssignmentCreateRequest) {
|
||||||
const { name, groupId } = request;
|
const { name, groupId } = request;
|
||||||
if (this.manualAssignments.has(name)) {
|
if (this.manualAssignments.has(name)) {
|
||||||
throw new lib.RequestError(`Assignment for '${name}' already exists`);
|
throw new lib.ConflictError(`Assignment for '${name}' already exists`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const assignment = new messages.AssignmentRecord(name, groupId);
|
const assignment = new messages.AssignmentRecord(name, groupId);
|
||||||
@@ -297,7 +297,7 @@ export class ControllerPlugin {
|
|||||||
async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) {
|
async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) {
|
||||||
const assignment = request.assignment;
|
const assignment = request.assignment;
|
||||||
if (!this.manualAssignments.has(assignment.name)) {
|
if (!this.manualAssignments.has(assignment.name)) {
|
||||||
throw new lib.RequestError(`Assignment for '${assignment.name}' does not exist`);
|
throw new lib.NotFoundError(`Assignment for '${assignment.name}' does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.manualAssignments.set(assignment);
|
this.manualAssignments.set(assignment);
|
||||||
@@ -308,7 +308,7 @@ export class ControllerPlugin {
|
|||||||
|
|
||||||
const assignment = this.manualAssignments.getMutable(name);
|
const assignment = this.manualAssignments.getMutable(name);
|
||||||
if (!assignment) {
|
if (!assignment) {
|
||||||
throw new lib.RequestError(`Assignment for '${name}' does not exist`);
|
throw new lib.NotFoundError(`Assignment for '${name}' does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.manualAssignments.delete(assignment);
|
this.manualAssignments.delete(assignment);
|
||||||
@@ -327,7 +327,7 @@ export class ControllerPlugin {
|
|||||||
|
|
||||||
const assignment = this.manualAssignments.get(request.name);
|
const assignment = this.manualAssignments.get(request.name);
|
||||||
if (!assignment) {
|
if (!assignment) {
|
||||||
throw new lib.RequestError(`Assignment for '${request.name}' does not exist`);
|
throw new lib.NotFoundError(`Assignment for '${request.name}' does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return assignment;
|
return assignment;
|
||||||
@@ -364,7 +364,7 @@ export class ControllerPlugin {
|
|||||||
async handleRoleMappingUpdateRequest(request: messages.RoleMappingUpdateRequest) {
|
async handleRoleMappingUpdateRequest(request: messages.RoleMappingUpdateRequest) {
|
||||||
const roleMapping = request.roleMapping;
|
const roleMapping = request.roleMapping;
|
||||||
if (roleMapping.id === undefined || !this.roleMappings.has(roleMapping.id)) {
|
if (roleMapping.id === undefined || !this.roleMappings.has(roleMapping.id)) {
|
||||||
throw new lib.RequestError(`Role mapping with ID ${roleMapping.id} does not exist`);
|
throw new lib.NotFoundError(`Role mapping with ID ${roleMapping.id} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const existing = new Set(
|
const existing = new Set(
|
||||||
@@ -386,7 +386,7 @@ export class ControllerPlugin {
|
|||||||
|
|
||||||
const mapping = this.roleMappings.getMutable(id);
|
const mapping = this.roleMappings.getMutable(id);
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
throw new lib.RequestError(`Role mapping with ID ${id} does not exist`);
|
throw new lib.NotFoundError(`Role mapping with ID ${id} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.roleMappings.delete(mapping);
|
this.roleMappings.delete(mapping);
|
||||||
@@ -395,7 +395,7 @@ export class ControllerPlugin {
|
|||||||
async handleRoleMappingGetRequest(request: messages.RoleMappingGetRequest) {
|
async handleRoleMappingGetRequest(request: messages.RoleMappingGetRequest) {
|
||||||
const mapping = this.roleMappings.get(request.id);
|
const mapping = this.roleMappings.get(request.id);
|
||||||
if (!mapping) {
|
if (!mapping) {
|
||||||
throw new lib.RequestError(`Role mapping with ID ${request.id} does not exist`);
|
throw new lib.NotFoundError(`Role mapping with ID ${request.id} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mapping;
|
return mapping;
|
||||||
|
|||||||
+10
-10
@@ -158,7 +158,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
controller.handle(messages.ReportGetRequest, async (request: messages.ReportGetRequest) => {
|
controller.handle(messages.ReportGetRequest, async (request: messages.ReportGetRequest) => {
|
||||||
const report = reports.get(request.id);
|
const report = reports.get(request.id);
|
||||||
if (!report) {
|
if (!report) {
|
||||||
throw new lib.RequestError(`Report with ID ${request.id} does not exist`);
|
throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`);
|
||||||
}
|
}
|
||||||
return report;
|
return report;
|
||||||
});
|
});
|
||||||
@@ -174,13 +174,13 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (!byPlayerName) {
|
if (!byPlayerName) {
|
||||||
throw new lib.RequestError("A report needs the name of the player making it");
|
throw new lib.ValidationError("A report needs the name of the player making it");
|
||||||
}
|
}
|
||||||
if (!request.reason.trim()) {
|
if (!request.reason.trim()) {
|
||||||
throw new lib.RequestError("A report needs a reason");
|
throw new lib.ValidationError("A report needs a reason");
|
||||||
}
|
}
|
||||||
if (listReports(request.playerName).some(report => report.byPlayerName === byPlayerName)) {
|
if (listReports(request.playerName).some(report => report.byPlayerName === byPlayerName)) {
|
||||||
throw new lib.RequestError(`${byPlayerName} has already reported ${request.playerName}`);
|
throw new lib.ConflictError(`${byPlayerName} has already reported ${request.playerName}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
let id = Math.random() * 2 ** 31 | 0;
|
let id = Math.random() * 2 ** 31 | 0;
|
||||||
@@ -199,7 +199,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
controller.handle(messages.ReportDeleteRequest, async (request: messages.ReportDeleteRequest) => {
|
controller.handle(messages.ReportDeleteRequest, async (request: messages.ReportDeleteRequest) => {
|
||||||
const report = reports.getMutable(request.id);
|
const report = reports.getMutable(request.id);
|
||||||
if (!report) {
|
if (!report) {
|
||||||
throw new lib.RequestError(`Report with ID ${request.id} does not exist`);
|
throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`);
|
||||||
}
|
}
|
||||||
reports.delete(report);
|
reports.delete(report);
|
||||||
});
|
});
|
||||||
@@ -207,7 +207,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
controller.handle(messages.ReportSetReadRequest, async (request: messages.ReportSetReadRequest) => {
|
controller.handle(messages.ReportSetReadRequest, async (request: messages.ReportSetReadRequest) => {
|
||||||
const report = reports.getMutable(request.id);
|
const report = reports.getMutable(request.id);
|
||||||
if (!report) {
|
if (!report) {
|
||||||
throw new lib.RequestError(`Report with ID ${request.id} does not exist`);
|
throw new lib.NotFoundError(`Report with ID ${request.id} does not exist`);
|
||||||
}
|
}
|
||||||
report.isRead = request.isRead;
|
report.isRead = request.isRead;
|
||||||
reports.set(report);
|
reports.set(report);
|
||||||
@@ -216,14 +216,14 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
controller.handle(messages.WatchListAddRequest, async (request: messages.WatchListAddRequest, src: lib.Address) => {
|
controller.handle(messages.WatchListAddRequest, async (request: messages.WatchListAddRequest, src: lib.Address) => {
|
||||||
const playerName = request.playerName.trim();
|
const playerName = request.playerName.trim();
|
||||||
if (!playerName) {
|
if (!playerName) {
|
||||||
throw new lib.RequestError("A player name is required");
|
throw new lib.ValidationError("A player name is required");
|
||||||
}
|
}
|
||||||
if (!request.reason.trim()) {
|
if (!request.reason.trim()) {
|
||||||
throw new lib.RequestError("A reason is required");
|
throw new lib.ValidationError("A reason is required");
|
||||||
}
|
}
|
||||||
const existing = watchList.get(playerName.toLowerCase());
|
const existing = watchList.get(playerName.toLowerCase());
|
||||||
if (existing) {
|
if (existing) {
|
||||||
throw new lib.RequestError(`${existing.playerName} is already on the watch list`);
|
throw new lib.ConflictError(`${existing.playerName} is already on the watch list`);
|
||||||
}
|
}
|
||||||
|
|
||||||
const entry = new messages.WatchListRecord(playerName, request.reason.trim(), controlUserName(src), Date.now());
|
const entry = new messages.WatchListRecord(playerName, request.reason.trim(), controlUserName(src), Date.now());
|
||||||
@@ -234,7 +234,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
controller.handle(messages.WatchListRemoveRequest, async (request: messages.WatchListRemoveRequest) => {
|
controller.handle(messages.WatchListRemoveRequest, async (request: messages.WatchListRemoveRequest) => {
|
||||||
const entry = watchList.getMutable(request.playerName.toLowerCase());
|
const entry = watchList.getMutable(request.playerName.toLowerCase());
|
||||||
if (!entry) {
|
if (!entry) {
|
||||||
throw new lib.RequestError(`${request.playerName} is not on the watch list`);
|
throw new lib.NotFoundError(`${request.playerName} is not on the watch list`);
|
||||||
}
|
}
|
||||||
watchList.delete(entry);
|
watchList.delete(entry);
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -102,7 +102,7 @@ t.test("instance plugin", t2 => {
|
|||||||
|
|
||||||
t2.test("exp_reports:create prints a refusal to the reporter", async t3 => {
|
t2.test("exp_reports:create prints a refusal to the reporter", async t3 => {
|
||||||
const { state, createIPC } = await startPlugin(t3);
|
const { state, createIPC } = await startPlugin(t3);
|
||||||
state.failNext = new lib.RequestError("dave has already reported bob");
|
state.failNext = new lib.ConflictError("dave has already reported bob");
|
||||||
await createIPC({ player_name: "bob", by_player_name: "dave", reason: "griefing" });
|
await createIPC({ player_name: "bob", by_player_name: "dave", reason: "griefing" });
|
||||||
|
|
||||||
const { receiver, payload } = decodeRcon(state.rcons[0]);
|
const { receiver, payload } = decodeRcon(state.rcons[0]);
|
||||||
@@ -113,7 +113,7 @@ t.test("instance plugin", t2 => {
|
|||||||
t2.test("text that closes a long bracket stays inside the json", async t3 => {
|
t2.test("text that closes a long bracket stays inside the json", async t3 => {
|
||||||
const { state, createIPC } = await startPlugin(t3);
|
const { state, createIPC } = await startPlugin(t3);
|
||||||
const message = "]=]) game.print(1) --[==[ ]==] ]===]";
|
const message = "]=]) game.print(1) --[==[ ]==] ]===]";
|
||||||
state.failNext = new lib.RequestError(message);
|
state.failNext = new lib.ConflictError(message);
|
||||||
await createIPC({ player_name: "bob", by_player_name: "dave", reason: message });
|
await createIPC({ player_name: "bob", by_player_name: "dave", reason: message });
|
||||||
|
|
||||||
const { payload } = decodeRcon(state.rcons[0]);
|
const { payload } = decodeRcon(state.rcons[0]);
|
||||||
|
|||||||
@@ -147,7 +147,7 @@ export class ControllerPlugin {
|
|||||||
async handleRoleMetaUpdateRequest(request: messages.RoleMetaUpdateRequest) {
|
async handleRoleMetaUpdateRequest(request: messages.RoleMetaUpdateRequest) {
|
||||||
const meta = request.meta;
|
const meta = request.meta;
|
||||||
if (!this.controller.roles.has(meta.id)) {
|
if (!this.controller.roles.has(meta.id)) {
|
||||||
throw new lib.RequestError(`Role with ID ${meta.id} does not exist`);
|
throw new lib.NotFoundError(`Role with ID ${meta.id} does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
this.roleMeta.set(meta);
|
this.roleMeta.set(meta);
|
||||||
@@ -248,12 +248,12 @@ export class ControllerPlugin {
|
|||||||
async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) {
|
async handleAssignmentUpdateRequest(request: messages.AssignmentUpdateRequest) {
|
||||||
const user = this.controller.users.getByNameMutable(request.name);
|
const user = this.controller.users.getByNameMutable(request.name);
|
||||||
if (!user) {
|
if (!user) {
|
||||||
throw new lib.RequestError(`User '${request.name}' does not exist`);
|
throw new lib.NotFoundError(`User '${request.name}' does not exist`);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (const roleId of [...request.assign, ...request.unassign]) {
|
for (const roleId of [...request.assign, ...request.unassign]) {
|
||||||
if (!this.controller.roles.has(roleId)) {
|
if (!this.controller.roles.has(roleId)) {
|
||||||
throw new lib.RequestError(`Role with ID ${roleId} does not exist`);
|
throw new lib.NotFoundError(`Role with ID ${roleId} does not exist`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -175,7 +175,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
const rolesPlugin = RolesPlugin.get(controller);
|
const rolesPlugin = RolesPlugin.get(controller);
|
||||||
const groupsPlugin = GroupsPlugin.get(controller);
|
const groupsPlugin = GroupsPlugin.get(controller);
|
||||||
if (!rolesPlugin || !groupsPlugin) {
|
if (!rolesPlugin || !groupsPlugin) {
|
||||||
throw new lib.RequestError("Seeding requires the exp_roles and exp_groups plugins");
|
throw new lib.UnavailableError("Seeding requires the exp_roles and exp_groups plugins");
|
||||||
}
|
}
|
||||||
|
|
||||||
const roleIds = new Map<string, number>();
|
const roleIds = new Map<string, number>();
|
||||||
@@ -214,7 +214,7 @@ export default async function (context: ControllerPluginContext) {
|
|||||||
try {
|
try {
|
||||||
values = validateFeatureValues(request.id, request.values);
|
values = validateFeatureValues(request.id, request.values);
|
||||||
} catch (err: any) {
|
} catch (err: any) {
|
||||||
throw new lib.RequestError(err.message);
|
throw new lib.ValidationError(err.message);
|
||||||
}
|
}
|
||||||
|
|
||||||
const feature = new messages.FeatureRecord(request.id, request.enabled, values);
|
const feature = new messages.FeatureRecord(request.id, request.enabled, values);
|
||||||
|
|||||||
Reference in new issue
Block a user