mirror of
https://github.com/clusterio/clusterio.git
synced 2026-11-11 23:04:52 +09:00
Replace bootstrap methods with async factories
Controller.bootstrap and Host.bootstrap returned constructor arguments that the caller had to spread into new Controller/Host, and DatastoreProvider.bootstrap did the same for datastores. They are replaced by Controller.fromConfig, Host.fromConfig and KeyValueDatastore/SubscribableDatastore.fromProvider, which load the data and return the finished instance. Closes #1126 Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
1 parent
c3abf27266
commit
d7fc3aaec4
8 files changed
+133
-57
No files matched your search
@@ -57,6 +57,38 @@ describe("controller/src/Controller", function() {
|
||||
assert(list.check(ip), `${ip} missing from list`);
|
||||
}
|
||||
}
|
||||
describe(".fromConfig()", function() {
|
||||
let dir;
|
||||
beforeEach(async function() {
|
||||
dir = await fs.mkdtemp(path.join(os.tmpdir(), "clusterio-controller-"));
|
||||
});
|
||||
afterEach(async function() {
|
||||
await fs.rm(dir, { recursive: true, force: true });
|
||||
});
|
||||
it("should load datastores and mods from disk", async function() {
|
||||
const databaseDirectory = path.join(dir, "database");
|
||||
const modsDirectory = path.join(dir, "mods");
|
||||
await fs.mkdir(databaseDirectory);
|
||||
await fs.writeFile(path.join(databaseDirectory, "notes.json"), JSON.stringify([
|
||||
{ resourceType: "instance", resourceId: "100", content: "hello" },
|
||||
]));
|
||||
const config = new ControllerConfig("controller", {
|
||||
"controller.version": controllerVersion,
|
||||
"controller.database_directory": databaseDirectory,
|
||||
"controller.mods_directory": modsDirectory,
|
||||
});
|
||||
|
||||
const loaded = await Controller.fromConfig({}, [], config, true, false);
|
||||
assert(loaded instanceof Controller);
|
||||
assert.equal(loaded.canRestart, true);
|
||||
assert.equal(loaded.recoveryMode, false);
|
||||
assert.equal(loaded.notes.get("instance/100").content, "hello");
|
||||
assert.equal(loaded.modStore.modsDirectory, modsDirectory);
|
||||
assert(loaded.roles.size > 0, "default roles were not added");
|
||||
assert(loaded.modPacks.size > 0, "default mod packs were not added");
|
||||
await fs.access(modsDirectory);
|
||||
});
|
||||
});
|
||||
describe(".loadJsonObject()", function() {
|
||||
let dir;
|
||||
before(async function() {
|
||||
|
||||
@@ -62,6 +62,21 @@ describe("host/src/Host", function() {
|
||||
});
|
||||
});
|
||||
describe("class Host", function() {
|
||||
describe(".fromConfig()", function() {
|
||||
const modsDirectory = path.join("temp", "test", "host_from_config", "mods");
|
||||
beforeEach(async function() {
|
||||
await fs.rm(path.dirname(modsDirectory), { recursive: true, force: true });
|
||||
});
|
||||
it("should create the mods directory and load the mod store", async function() {
|
||||
const hostConfig = new lib.HostConfig("host", { "host.mods_directory": modsDirectory });
|
||||
const host = await Host.fromConfig(new HostConnector(hostConfig, []), hostConfig, [], true, false);
|
||||
assert(host instanceof Host);
|
||||
assert.equal(host.canRestart, true);
|
||||
assert.equal(host.recoveryMode, false);
|
||||
assert.equal(host.modStore.modsDirectory, modsDirectory);
|
||||
await fs.access(modsDirectory);
|
||||
});
|
||||
});
|
||||
describe(".handleSyncUserListsEvent()", function() {
|
||||
const hostAddress = lib.Address.fromShorthand({ hostId: 1 });
|
||||
const instanceAddress = lib.Address.fromShorthand({ instanceId: 1 });
|
||||
|
||||
+29
-21
@@ -50,13 +50,6 @@ describe("lib/datastore", function() {
|
||||
it("can be constructed", function() {
|
||||
assert.deepEqual(datastoreProvider.methodCalls[0], ["constructor"]);
|
||||
});
|
||||
|
||||
it("can be bootstrapped", async function() {
|
||||
const rtn = await datastoreProvider.bootstrap();
|
||||
assert.equal(rtn[0], datastoreProvider);
|
||||
assert.equal(rtn[1], datastoreProvider.value);
|
||||
assert.deepEqual(datastoreProvider.methodCalls[1], ["load"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("class MemoryDatastoreProvider", function() {
|
||||
@@ -70,13 +63,13 @@ describe("lib/datastore", function() {
|
||||
|
||||
describe("constructor", function() {
|
||||
it("has a default value", async function() {
|
||||
const [, value] = await new lib.MemoryDatastoreProvider().bootstrap();
|
||||
const value = await new lib.MemoryDatastoreProvider().load();
|
||||
assert.notEqual(value, undefined);
|
||||
assert.notEqual(value, null);
|
||||
});
|
||||
it("can have a value given", async function() {
|
||||
const expectedValue = new Map([["foo", "bar"]]);
|
||||
const [, value] = await new lib.MemoryDatastoreProvider(expectedValue).bootstrap();
|
||||
const value = await new lib.MemoryDatastoreProvider(expectedValue).load();
|
||||
assert.deepEqual(value, expectedValue);
|
||||
});
|
||||
});
|
||||
@@ -116,7 +109,7 @@ describe("lib/datastore", function() {
|
||||
it("has default values", async function() {
|
||||
datastoreProvider = new lib.JsonDatastoreProvider(dataPath);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData));
|
||||
});
|
||||
it("can accept a fromJson method", async function() {
|
||||
@@ -125,7 +118,7 @@ describe("lib/datastore", function() {
|
||||
json => [json]
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData.map(([k, v]) => [k, [v]])));
|
||||
});
|
||||
it("can accept a migration method", async function() {
|
||||
@@ -135,7 +128,7 @@ describe("lib/datastore", function() {
|
||||
rawJson => ({ c: "foo", ...rawJson })
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map([...initialData, ["c", "foo"]]));
|
||||
});
|
||||
it("can accept a finalise method", async function() {
|
||||
@@ -146,7 +139,7 @@ describe("lib/datastore", function() {
|
||||
obj => [obj]
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData.map(([k, v]) => [k, [v]])));
|
||||
});
|
||||
});
|
||||
@@ -210,7 +203,7 @@ describe("lib/datastore", function() {
|
||||
it("has default values", async function() {
|
||||
datastoreProvider = new lib.JsonIdDatastoreProvider(dataPath);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData));
|
||||
});
|
||||
it("can accept a fromJson method", async function() {
|
||||
@@ -219,7 +212,7 @@ describe("lib/datastore", function() {
|
||||
json => ({...json, foo: true})
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData.map(v => ([v[0], {...v[1], foo: true}]))));
|
||||
});
|
||||
it("can accept a migration method", async function() {
|
||||
@@ -229,7 +222,7 @@ describe("lib/datastore", function() {
|
||||
rawJson => ([{ id: "c" }, ...rawJson])
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map([...initialData, ["c", { id: "c" }]]));
|
||||
});
|
||||
it("can accept a finalise method", async function() {
|
||||
@@ -240,7 +233,7 @@ describe("lib/datastore", function() {
|
||||
obj => ({...obj, foo: true})
|
||||
);
|
||||
|
||||
const [, value] = await datastoreProvider.bootstrap();
|
||||
const value = await datastoreProvider.load();
|
||||
assert.deepEqual(value, new Map(initialData.map(v => ([v[0], {...v[1], foo: true}]))));
|
||||
});
|
||||
});
|
||||
@@ -306,10 +299,6 @@ describe("lib/datastore", function() {
|
||||
datastore = new MockDatastore(datastoreProvider, datastoreProvider.value);
|
||||
assert.deepEqual(datastore.getData(), datastoreProvider.value);
|
||||
});
|
||||
it("accepts the return of bootstrap", async function() {
|
||||
datastore = new MockDatastore(...await datastoreProvider.bootstrap());
|
||||
assert.deepEqual(datastore.getData(), datastoreProvider.value);
|
||||
});
|
||||
});
|
||||
|
||||
describe("getFilePath", function() {
|
||||
@@ -478,6 +467,15 @@ describe("lib/datastore", function() {
|
||||
datastore.on("update", updates => eventsRaised.push(updates));
|
||||
});
|
||||
|
||||
describe("fromProvider", function() {
|
||||
it("loads data from the provider", async function() {
|
||||
datastore = await lib.KeyValueDatastore.fromProvider(datastoreProvider);
|
||||
assert(datastore instanceof lib.KeyValueDatastore);
|
||||
assert.equal(datastore.get("foo"), "fooValue");
|
||||
assert.deepEqual(datastoreProvider.methodCalls[1], ["load"]);
|
||||
});
|
||||
});
|
||||
|
||||
describe("set", function() {
|
||||
it("can set a value", function() {
|
||||
datastore.set("test", "testValue");
|
||||
@@ -571,6 +569,16 @@ describe("lib/datastore", function() {
|
||||
datastore.on("update", updates => eventsRaised.push(updates));
|
||||
});
|
||||
|
||||
describe("fromProvider", function() {
|
||||
it("loads data from the provider", async function() {
|
||||
datastore = await lib.SubscribableDatastore.fromProvider(datastoreProvider);
|
||||
assert(datastore instanceof lib.SubscribableDatastore);
|
||||
assert.equal(datastore.get("foo").id, "foo");
|
||||
assert.equal(datastore.lastUpdatedAtMs, 10);
|
||||
assert.deepEqual(datastoreProvider.methodCalls[1], ["load"]);
|
||||
});
|
||||
});
|
||||
|
||||
function forceFuture() {
|
||||
const future = {id: "future"};
|
||||
for (let i = 1; i < 100; i++) {
|
||||
|
||||
Reference in new issue
Block a user