Skip to content

Commit 00a51af

Browse files
committed
coherence feature flag for container instance
1 parent 01f554f commit 00a51af

File tree

4 files changed

+137
-49
lines changed

4 files changed

+137
-49
lines changed

scripts/ci.mjs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,7 @@ const containersConfig = JSON.stringify([
2525
{
2626
displayName: "ServerContainer",
2727
imageUrl: serverImageURL,
28+
environmentVariables: { ENABLE_COHERENCE_BACKEND: false },
2829
resourceConfig: {
2930
memoryLimitInGBs: 8,
3031
vcpusLimit: 1.5,

server/index.js

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,8 @@ let subClient;
2323
let cacheSession;
2424

2525
// FIXME Flag to use coherence
26-
const ENABLE_COHERENCE_BACKEND = process.env.ENABLE_COHERENCE_BACKEND === "true";
26+
const ENABLE_COHERENCE_BACKEND =
27+
process.env.ENABLE_COHERENCE_BACKEND === "true";
2728

2829
// FIXME coherence security, probably TLS, password would be easier to begin with
2930
const COHERENCE_SERVICE_HOST = process.env.COHERENCE_SERVICE_HOST
@@ -35,7 +36,10 @@ const COHERENCE_SERVICE_PORT = process.env.COHERENCE_SERVICE_PORT
3536
: 1408;
3637

3738
const coherenceAddress = `${COHERENCE_SERVICE_HOST}:${COHERENCE_SERVICE_PORT}`;
38-
logger.info(`Coherence URL: ${coherenceAddress}`);
39+
logger.info(`Coherence: ${ENABLE_COHERENCE_BACKEND ? "Enabled" : "Disabled"}`);
40+
if (ENABLE_COHERENCE_BACKEND) {
41+
logger.info(`Coherence URL: ${coherenceAddress}`);
42+
}
3943

4044
const ENABLE_REDIS_BACKEND = process.env.ENABLE_REDIS_BACKEND === "true";
4145

@@ -77,7 +81,9 @@ if (ENABLE_REDIS_BACKEND) {
7781
start(httpServer, port, cacheSession, pubClient, subClient);
7882
});
7983
} else {
80-
createCacheSession().then(() => { start(httpServer, port, cacheSession)});
84+
createCacheSession().then(() => {
85+
start(httpServer, port, cacheSession);
86+
});
8187
}
8288

8389
function onSignal() {
@@ -131,14 +137,19 @@ createTerminus(httpServer, {
131137

132138
async function createCacheSession() {
133139
return new Promise((resolve, reject) => {
134-
try {
135-
const opts = new Options();
136-
opts.address = coherenceAddress;
137-
cacheSession = new Session(opts);
138-
resolve(cacheSession);
139-
} catch (err) {
140-
logger.error(err.message);
141-
reject(err.message);
140+
if (ENABLE_COHERENCE_BACKEND) {
141+
try {
142+
const opts = new Options();
143+
opts.address = coherenceAddress;
144+
cacheSession = new Session(opts);
145+
resolve(cacheSession);
146+
} catch (err) {
147+
logger.error(err.message);
148+
reject(err.message);
149+
}
150+
} else {
151+
logger.info("Coherence is disabled");
152+
resolve(null);
142153
}
143154
});
144155
}

server/score.js

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,8 @@ import fetch from "node-fetch";
33
import pino from "pino";
44

55
dotenv.config({ path: "./config/.env" });
6-
// FIXME change log level based on NODE_ENV
7-
const logger = pino();
6+
const isProduction = process.env.NODE_ENV === "production";
7+
const logger = pino({ level: isProduction ? "warn" : "debug" });
88

99
let scoreFeatureFlag = true;
1010

@@ -18,7 +18,8 @@ if (!SCORE_SERVICE_PORT) {
1818
scoreFeatureFlag = false;
1919
logger.error(`SCORE_SERVICE_PORT not defined`);
2020
}
21-
if (!scoreFeatureFlag) {
21+
22+
if (scoreFeatureFlag) {
2223
const scoreServiceUrl = `${SCORE_SERVICE_HOST}:${SCORE_SERVICE_PORT}`;
2324
logger.info(`Connecting to Score on ${scoreServiceUrl}`);
2425
}

server/server.js

Lines changed: 110 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,9 @@ logger.info(`Server version ${version}`);
1616
const serverId = short.generate();
1717
logger.info(`Server ${serverId}`);
1818

19+
const ENABLE_COHERENCE_BACKEND =
20+
process.env.ENABLE_COHERENCE_BACKEND === "true";
21+
1922
const BROADCAST_REFRESH_UPDATE = process.env.BROADCAST_REFRESH_UPDATE
2023
? parseInt(process.env.BROADCAST_REFRESH_UPDATE)
2124
: 50;
@@ -63,11 +66,17 @@ export async function start(
6366
io.adapter(createAdapter(pubClient, subClient));
6467
}
6568

66-
// FIXME consider ENABLE_COHERENCE_BACKEND flag
67-
mapPlayersTraces = await cacheSession.getMap("playerTraces");
68-
mapPlayersInfo = await cacheSession.getMap("playersInfo");
69-
mapTrash = await cacheSession.getMap("trash");
70-
mapMarineLife = await cacheSession.getMap("marineLife");
69+
if (ENABLE_COHERENCE_BACKEND) {
70+
mapPlayersTraces = await cacheSession.getMap("playerTraces");
71+
mapPlayersInfo = await cacheSession.getMap("playersInfo");
72+
mapTrash = await cacheSession.getMap("trash");
73+
mapMarineLife = await cacheSession.getMap("marineLife");
74+
} else {
75+
mapPlayersTraces = {};
76+
mapPlayersInfo = {};
77+
mapTrash = {};
78+
mapMarineLife = {};
79+
}
7180

7281
io.on("connection", async (socket) => {
7382
let playerIdForSocket;
@@ -80,23 +89,41 @@ export async function start(
8089
worldSizeZ: WORLD_SIZE_Z,
8190
});
8291

83-
const trashFromCache = await readCacheEntries(mapTrash);
84-
const marineLifeFromCache = await readCacheEntries(mapMarineLife);
92+
const trashFromCache = ENABLE_COHERENCE_BACKEND
93+
? await readCacheEntries(mapTrash)
94+
: mapTrash;
95+
const marineLifeFromCache = ENABLE_COHERENCE_BACKEND
96+
? await readCacheEntries(mapMarineLife)
97+
: mapMarineLife;
8598
socket.emit("items.all", { ...trashFromCache, ...marineLifeFromCache });
8699

87100
// FIXME scope this to surrounding players only
88-
socket.emit("player.info.all", await readCacheEntries(mapPlayersInfo));
101+
socket.emit(
102+
"player.info.all",
103+
ENABLE_COHERENCE_BACKEND
104+
? await readCacheEntries(mapPlayersInfo)
105+
: mapPlayersInfo
106+
);
89107

90108
// FIXME send random starting position
91109
socket.emit("game.on", {});
92110

93111
socket.on("player.info.joining", async ({ id, name }) => {
94-
await writeCache(mapPlayersInfo, id, { name });
112+
if (ENABLE_COHERENCE_BACKEND) {
113+
await writeCache(mapPlayersInfo, id, { name });
114+
} else {
115+
mapPlayersInfo[id] = { name };
116+
}
95117
});
96118

97119
socket.on("game.start", async ({ playerId, playerName }) => {
98120
playerIdForSocket = playerId;
99-
await writeCache(mapPlayersInfo, playerId, { name: playerName });
121+
const body = { name: playerName };
122+
if (ENABLE_COHERENCE_BACKEND) {
123+
await writeCache(mapPlayersInfo, playerId, body);
124+
} else {
125+
mapPlayersInfo[playerId] = body;
126+
}
100127
io.emit("player.info.joined", {
101128
id: playerId,
102129
name: playerName,
@@ -105,29 +132,48 @@ export async function start(
105132
setTimeout(async () => {
106133
socket.emit("game.end", { playerId });
107134
io.emit("player.info.left", playerId);
108-
await deleteCache(mapPlayersTraces, playerId);
135+
if (ENABLE_COHERENCE_BACKEND) {
136+
await deleteCache(mapPlayersTraces, playerId);
137+
await deleteCache(mapPlayersInfo, playerId);
138+
} else {
139+
delete mapPlayersTraces[playerId];
140+
delete mapPlayersInfo[playerId];
141+
}
109142
await deleteCurrentScore(playerId);
110-
await deleteCache(mapPlayersInfo, playerId);
111143
playerIdForSocket = undefined;
112144
}, GAME_DURATION_IN_SECONDS * 1000);
113145
});
114146

115147
socket.on("player.trace.change", async ({ id, ...traceData }) => {
116148
const body = { ...traceData, updated: new Date() };
117-
await writeCache(mapPlayersTraces, id, body);
149+
if (ENABLE_COHERENCE_BACKEND) {
150+
await writeCache(mapPlayersTraces, id, body);
151+
} else {
152+
mapPlayersTraces[id] = body;
153+
}
118154
});
119155

120156
socket.on("items.collision", async ({ itemId, playerId, playerName }) => {
121-
if (await mapTrash.has(itemId)) {
122-
await deleteCache(mapTrash, itemId);
157+
const existTrash = ENABLE_COHERENCE_BACKEND
158+
? await mapTrash.has(itemId)
159+
: mapTrash[itemId];
160+
const existMarineLife = ENABLE_COHERENCE_BACKEND
161+
? await mapMarineLife.has(itemId)
162+
: mapMarineLife[itemId];
163+
if (existTrash) {
164+
ENABLE_COHERENCE_BACKEND
165+
? await deleteCache(mapTrash, itemId)
166+
: delete mapTrash[itemId];
123167
io.emit("item.destroy", itemId);
124168
const jsonResponse = await postCurrentScore(
125169
playerId,
126170
playerName,
127171
"INCREMENT"
128172
);
129-
} else if (await mapMarineLife.has(itemId)) {
130-
await deleteCache(mapMarineLife, itemId);
173+
} else if (existMarineLife) {
174+
ENABLE_COHERENCE_BACKEND
175+
? await deleteCache(mapMarineLife, itemId)
176+
: delete mapMarineLife[itemId];
131177
io.emit("item.destroy", itemId);
132178
const jsonResponse = await postCurrentScore(
133179
playerId,
@@ -139,8 +185,13 @@ export async function start(
139185

140186
socket.on("disconnect", async (reason) => {
141187
io.emit("player.info.left", playerIdForSocket);
142-
await deleteCache(mapPlayersTraces, playerIdForSocket);
143-
await deleteCache(mapPlayersInfo, playerIdForSocket);
188+
if (ENABLE_COHERENCE_BACKEND) {
189+
await deleteCache(mapPlayersTraces, playerIdForSocket);
190+
await deleteCache(mapPlayersInfo, playerIdForSocket);
191+
} else {
192+
delete mapPlayersTraces[playerIdForSocket];
193+
delete mapPlayersInfo[playerIdForSocket];
194+
}
144195
logger.info(`${playerIdForSocket} disconnected because ${reason}`);
145196
playerIdForSocket = undefined;
146197
});
@@ -153,15 +204,23 @@ export async function start(
153204
// broadcast all players traces
154205
setInterval(async () => {
155206
// FIXME scope this to surrounding players only
156-
const traces = await readCacheEntries(mapPlayersTraces);
207+
const traces = ENABLE_COHERENCE_BACKEND
208+
? await readCacheEntries(mapPlayersTraces)
209+
: mapPlayersTraces;
157210
io.emit("player.trace.all", traces);
158211
}, BROADCAST_REFRESH_UPDATE);
159212

160213
// refresh items
161214
setInterval(async () => {
162-
const numberOfPlayers = await mapPlayersInfo.size;
163-
const numberOfTrash = await mapTrash.size;
164-
const numberOfMarineLife = await mapMarineLife.size;
215+
const numberOfPlayers = ENABLE_COHERENCE_BACKEND
216+
? await mapPlayersInfo.size
217+
: Object.keys(mapPlayersInfo).length;
218+
const numberOfTrash = ENABLE_COHERENCE_BACKEND
219+
? await mapTrash.size
220+
: Object.keys(mapTrash).length;
221+
const numberOfMarineLife = ENABLE_COHERENCE_BACKEND
222+
? await mapMarineLife.size
223+
: Object.keys(mapMarineLife).length;
165224
const deltaOfDesiredNumberOfTrash = numberOfPlayers - numberOfTrash;
166225
const deltaOfDesiredNumberOfMarineLife =
167226
numberOfPlayers * 2 - numberOfMarineLife;
@@ -171,18 +230,21 @@ export async function start(
171230
extraTrashPoll[id] = trashData;
172231
io.emit("item.new", { id, data: extraTrashPoll[id] });
173232
}
174-
Object.keys(extraTrashPoll).forEach(
175-
async (key) => await writeCache(mapTrash, key, extraTrashPoll[key])
176-
);
233+
Object.keys(extraTrashPoll).forEach(async (key) => {
234+
ENABLE_COHERENCE_BACKEND
235+
? await writeCache(mapTrash, key, extraTrashPoll[key])
236+
: (mapTrash[key] = extraTrashPoll[key]);
237+
});
177238
const extraMarineLifePoll = {};
178239
for (let index = 0; index < deltaOfDesiredNumberOfMarineLife; index++) {
179240
const { id, ...marineLifeData } = createObject("turtle");
180241
extraMarineLifePoll[id] = marineLifeData;
181242
io.emit("item.new", { id, data: extraMarineLifePoll[id] });
182243
}
183-
Object.keys(extraMarineLifePoll).forEach(
184-
async (key) =>
185-
await writeCache(mapMarineLife, key, extraMarineLifePoll[key])
244+
Object.keys(extraMarineLifePoll).forEach(async (key) =>
245+
ENABLE_COHERENCE_BACKEND
246+
? await writeCache(mapMarineLife, key, extraMarineLifePoll[key])
247+
: (mapMarineLife[key] = extraMarineLifePoll[key])
186248
);
187249
}, BROADCAST_ITEMS_IN_SECONDS * 1000);
188250

@@ -203,24 +265,37 @@ export async function start(
203265
// FIXME can we delete them without adding elapsed to all of them?
204266
// FIXME can we use TTL from Coherence
205267
// FIXME do we need clean up stales to begin with?
206-
const traces = await readCacheEntries(mapPlayersTraces);
268+
const traces = ENABLE_COHERENCE_BACKEND
269+
? await readCacheEntries(mapPlayersTraces)
270+
: mapPlayersTraces;
207271
const elapsedTimesById = Object.entries(traces).map((player) => ({
208272
id: player[0],
209273
elapsed: now - player[1].updated,
210274
}));
211275
const staleIds = elapsedTimesById.filter((e) => e.elapsed > 250);
212276
staleIds.forEach(async (p) => {
213277
logger.info(`Stale player ${p.id} by ${p.elapsed}ms`);
214-
await deleteCache(mapPlayersTraces, p.id);
215-
await deleteCache(mapPlayersInfo, p.id);
278+
if (ENABLE_COHERENCE_BACKEND) {
279+
await deleteCache(mapPlayersTraces, p.id);
280+
await deleteCache(mapPlayersInfo, p.id);
281+
} else {
282+
delete mapPlayersTraces[p.id];
283+
delete mapPlayersInfo[p.id];
284+
}
216285
io.emit("player.info.left", p.id);
217286
});
218287
}, CLEANUP_STALE_IN_SECONDS * 1000);
219288

220289
setInterval(async () => {
221-
const numPlayers = await mapPlayersInfo.size;
222-
const numTrash = await mapTrash.size;
223-
const numMarineLife = await mapMarineLife.size;
290+
const numPlayers = ENABLE_COHERENCE_BACKEND
291+
? await mapPlayersInfo.size
292+
: Object.keys(mapPlayersInfo).length;
293+
const numTrash = ENABLE_COHERENCE_BACKEND
294+
? await mapTrash.size
295+
: Object.keys(mapTrash).length;
296+
const numMarineLife = ENABLE_COHERENCE_BACKEND
297+
? await mapMarineLife.size
298+
: Object.keys(mapMarineLife).length;
224299
logger.info(
225300
`${numPlayers} Players, ${numTrash} Trash items and ${numMarineLife} Marine Life`
226301
);

0 commit comments

Comments
 (0)