mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-15 07:24:52 +09:00
Keep a newer queue change over a queue reply it overtook
A QueueEvent arriving in the same socket read as a QueueSyncRequest reply is applied before the reply, which then wrote the older queue over it. Skip the reply when a QueueEvent was applied while it was in flight. Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
1 parent
fd39e2a171
commit
b10807b6d6
2 files changed
+19
No files matched your search
@@ -26,6 +26,7 @@ type IpcQueue = { queue: unknown, player?: string };
|
||||
export default async function(context: InstancePluginContext) {
|
||||
const { instance, logger, plugin } = context;
|
||||
let syncStarted = false;
|
||||
let queueEventsApplied = 0;
|
||||
|
||||
// Commands are sent one at a time so they execute in order
|
||||
let rconQueue: Promise<unknown> = Promise.resolve();
|
||||
@@ -50,7 +51,13 @@ export default async function(context: InstancePluginContext) {
|
||||
|
||||
// queue null asks for the cluster queue without seeding it
|
||||
async function followQueue(queue: string[] | null, player: string | null) {
|
||||
let applied = queueEventsApplied;
|
||||
let result = await instance.sendTo("controller", new QueueSyncRequest(queue, player));
|
||||
// A QueueEvent handled meanwhile is at least as new as this reply, since the controller broadcasts every
|
||||
// queue change in order with its replies. Arriving in the same read, it is applied before the reply.
|
||||
if (queueEventsApplied !== applied) {
|
||||
return;
|
||||
}
|
||||
await applyQueue({ queue: result });
|
||||
}
|
||||
|
||||
@@ -116,6 +123,7 @@ export default async function(context: InstancePluginContext) {
|
||||
if (event.player !== null) {
|
||||
data.player = event.player;
|
||||
}
|
||||
queueEventsApplied += 1;
|
||||
await applyQueue(data);
|
||||
});
|
||||
|
||||
|
||||
@@ -117,6 +117,17 @@ describe("research_sync instance", function() {
|
||||
instance.sendTo = async () => { throw new Error("gone"); };
|
||||
await instance.hooks.controllerConnectionEvent.invoke("connect");
|
||||
});
|
||||
it("should not let the reply overwrite a newer QueueEvent delivered with it", async function() {
|
||||
// As if the reply and the broadcast came in one socket read: the event is handled before the
|
||||
// reply resolves the request's await
|
||||
instance.sendTo = async (dst, message) => {
|
||||
sent.push(message);
|
||||
mock.getHandler(instance, QueueEvent)(new QueueEvent(["new"], null, "B"));
|
||||
return ["old"];
|
||||
};
|
||||
await instance.hooks.controllerConnectionEvent.invoke("connect");
|
||||
assert.equal(lastCommand(), applyCommand({ queue: ["new"], instance: "B" }));
|
||||
});
|
||||
});
|
||||
|
||||
it("should forward queue changes from the game", async function() {
|
||||
|
||||
Reference in new issue
Block a user