Skip to content

Commit c967c00

Browse files
committed
Add env vars. Add ws broadcast when making moves and comments.
1 parent 9280853 commit c967c00

File tree

2 files changed

+76
-6
lines changed

2 files changed

+76
-6
lines changed

api/abstractplay.ts

Lines changed: 73 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33

44
import { DynamoDBClient } from '@aws-sdk/client-dynamodb';
55
import { DynamoDBDocumentClient, PutCommand, GetCommand, UpdateCommand, DeleteCommand, QueryCommand, QueryCommandOutput, BatchWriteCommand, QueryCommandInput } from '@aws-sdk/lib-dynamodb';
6-
import { SQSClient, SendMessageCommand, SendMessageRequest } from "@aws-sdk/client-sqs";
6+
import { SQSClient, SendMessageCommand, SendMessageCommandOutput, SendMessageRequest } from "@aws-sdk/client-sqs";
77
import { v4 as uuid } from 'uuid';
88
import { gameinfo, GameFactory, GameBase, GameBaseSimultaneous, type APGamesInformation } from '@abstractplay/gameslib';
99
import { SESClient, SendEmailCommand } from '@aws-sdk/client-ses';
@@ -170,6 +170,7 @@ type MeData = {
170170
challengesAccepted?: FullChallenge[];
171171
standingChallenges?: FullChallenge[];
172172
realStanding?: StandingChallenge[];
173+
connections: number;
173174
}
174175

175176
type Rating = {
@@ -405,6 +406,14 @@ type StandingChallengeRec = {
405406
standing: StandingChallenge[];
406407
};
407408

409+
type WsMsgBody = {
410+
domainName: string;
411+
stage: string;
412+
verb: string;
413+
payload?: any;
414+
exclude?: string[];
415+
};
416+
408417
const sleep = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
409418

410419
async function sendCommandWithRetry(command: any, maxRetries = 8, initialDelay = 100, maxDelay = 5000) {
@@ -527,7 +536,7 @@ async function verifyAndCorrectRatingsCountWithData(metaGame: string, actualRati
527536

528537
function setsEqual(a: Set<any>, b: Set<any>): boolean {
529538
if (a.size !== b.size) return false;
530-
for (let item of a) {
539+
for (const item of a) {
531540
if (!b.has(item)) return false;
532541
}
533542
return true;
@@ -1767,6 +1776,9 @@ async function me(claim: PartialClaims, pars: { size: string, vars: string, upda
17671776
UpdateExpression: "set lastSeen = :dt"
17681777
}));
17691778

1779+
// Get number of current connections
1780+
const connections = await countByPk("wsConnections");
1781+
17701782
let data = null;
17711783
console.log(`Fetching challenges`);
17721784
let tagData, paletteData, standingData;
@@ -1832,6 +1844,7 @@ async function me(claim: PartialClaims, pars: { size: string, vars: string, upda
18321844
"challengesAccepted": (data[2] as any[]).map(d => d.Item),
18331845
"standingChallenges": (data[3] as any[]).map(d => d.Item),
18341846
"realStanding": realStanding,
1847+
"connections": connections,
18351848
} as MeData, Set_toJSON),
18361849
headers
18371850
};
@@ -1853,6 +1866,7 @@ async function me(claim: PartialClaims, pars: { size: string, vars: string, upda
18531866
tags,
18541867
palettes,
18551868
"realStanding": realStanding,
1869+
"connections": connections,
18561870
} as MeData, Set_toJSON),
18571871
headers
18581872
}
@@ -3413,7 +3427,7 @@ async function submitMove(userid: string, pars: { id: string, move: string, draw
34133427
const simultaneous = flags !== undefined && flags.includes('simultaneous');
34143428
const lastMoveTime = (new Date(engine.stack[engine.stack.length - 1]._timestamp)).getTime();
34153429
let autoMoves = 0;
3416-
let list: Promise<any>[] = [];
3430+
const list: Promise<any>[] = [];
34173431

34183432
try {
34193433
if (pars.move === "resign") {
@@ -3609,6 +3623,9 @@ async function submitMove(userid: string, pars: { id: string, move: string, draw
36093623
await realPingBot(game.metaGame, game.id, game);
36103624
await Promise.all(list);
36113625

3626+
// broadcasting that state has updated
3627+
await wsBroadcast("game", {"meta": pars.metaGame, "id": pars.id}, [userid]);
3628+
36123629
// TODO: Rehydrate state, run it through the stripper, and then replace with the new, stripped state
36133630
if (game.gameEnded === undefined) {
36143631
const engine = GameFactory(game.metaGame, game.state);
@@ -4344,7 +4361,7 @@ function applyMove(
43444361
}
43454362
}
43464363

4347-
let work: Promise<any>[] = [];
4364+
const work: Promise<any>[] = [];
43484365
if (!engine.gameover) {
43494366
if (explorations[0] && explorations[0].length > 0) {
43504367
// save back the updated exploration for player 0
@@ -4442,7 +4459,7 @@ async function updateLastChatForPlayers(
44424459
metaGame: string,
44434460
players: {[k: string]: any; id: string}[],
44444461
currentUserId: string,
4445-
allowReAdd: boolean = false // Only true for completed games via saveExploration
4462+
allowReAdd = false // Only true for completed games via saveExploration
44464463
) {
44474464
console.log(`Updating lastChat for all players of game ${gameId}`);
44484465

@@ -4630,6 +4647,11 @@ async function submitComment(userid: string, pars: { id: string; players?: {[k:
46304647
false // Don't re-add game to list for in-game comments
46314648
);
46324649
}
4650+
4651+
if (pars.metaGame) {
4652+
// broadcasting that state has updated
4653+
await wsBroadcast("game", {"meta": pars.metaGame, "id": pars.id}, [userid]);
4654+
}
46334655
}
46344656

46354657
async function saveExploration(userid: string, pars: { public: boolean, game: string; metaGame: string; move: number; version: number; tree: Exploration; updateCommentedFlag?: number; gameEnded?: number; updateLastChat?: boolean; players?: {[k: string]: any; id: string}[]; }) {
@@ -7628,7 +7650,7 @@ async function sendPush(opts: PushOptions) {
76287650
}
76297651

76307652
if(subscription !== undefined) {
7631-
// treat both 410 and 404 as permanent. There are a LOT of 404 web push errors in the logs and apparently these are because since June2024 the Chrome/FCM push service has changed the way it reports stale or deleted web‑push registrations.
7653+
// treat both 410 and 404 as permanent. There are a LOT of 404 web push errors in the logs and apparently these are because since June 2024 the Chrome/FCM push service has changed the way it reports stale or deleted web‑push registrations.
76327654
const PERMANENT_FAILURES = new Set([404, 410]);
76337655

76347656
try {
@@ -8687,3 +8709,48 @@ const getAllUsers = async (): Promise<FullUser[]> => {
86878709
return result
86888710
}
86898711

8712+
/**
8713+
* Count all items for a given partition key, paginating until complete.
8714+
*/
8715+
async function countByPk(
8716+
pkValue: string
8717+
): Promise<number> {
8718+
let total = 0;
8719+
let lastKey: Record<string, any> | undefined = undefined;
8720+
8721+
do {
8722+
const params: QueryCommandInput = {
8723+
TableName: process.env.ABSTRACT_PLAY_TABLE,
8724+
KeyConditionExpression: `pk = :pk`,
8725+
ExpressionAttributeValues: {
8726+
":pk": { S: pkValue },
8727+
},
8728+
Select: "COUNT",
8729+
ExclusiveStartKey: lastKey,
8730+
};
8731+
8732+
const result = await ddbDocClient.send(new QueryCommand(params));
8733+
8734+
total += result.Count ?? 0;
8735+
lastKey = result.LastEvaluatedKey;
8736+
} while (lastKey);
8737+
8738+
return total;
8739+
}
8740+
8741+
async function wsBroadcast (verb: string, payload: any, exclude?: string[]): Promise<SendMessageCommandOutput> {
8742+
// construct message
8743+
const body: WsMsgBody = {
8744+
domainName: process.env.WEBSOCKET_DOMAIN!,
8745+
stage: process.env.WEBSOCKET_STAGE!,
8746+
verb,
8747+
payload,
8748+
exclude,
8749+
}
8750+
const input: SendMessageRequest = {
8751+
QueueUrl: process.env.WEBSOCKET_SQS,
8752+
MessageBody: JSON.stringify(body),
8753+
}
8754+
const cmd = new SendMessageCommand(input);
8755+
return sqsClient.send(cmd);
8756+
}

serverless.yml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,6 +47,7 @@ custom:
4747
userpoolClient: 14mpql1tmvntup4p2anm4jt782
4848
sqsurl: https://sqs.us-east-1.amazonaws.com/153672715141/abstractplay-aiai-dev-aiai-queue
4949
wsDomain: qwmw4fb0l6.execute-api.us-east-1.amazonaws.com
50+
wsSqs: https://sqs.us-east-1.amazonaws.com/153672715141/abstractplay-ws-messages-dev
5051

5152
prod:
5253
profile: AbstractPlayProd
@@ -55,6 +56,7 @@ custom:
5556
userpoolClient: 2isan3ctk1aabt2v6r6aptlpg
5657
sqsurl: https://sqs.us-east-1.amazonaws.com/153672715141/abstractplay-aiai-prod-aiai-queue
5758
wsDomain: qwmw4fb0l6.execute-api.us-east-1.amazonaws.com
59+
wsSqs: https://sqs.us-east-1.amazonaws.com/153672715141/abstractplay-ws-messages-prod
5860

5961
package:
6062
# individually: true
@@ -84,6 +86,7 @@ provider:
8486
AIAI_USERID: SkQfHAjeDxs8eeEnScuYA
8587
WEBSOCKET_DOMAIN: ${self:custom.stageConfig.${self:provider.stage}.wsDomain}
8688
WEBSOCKET_STAGE: ${self:provider.stage}
89+
WEBSOCKET_SQS: ${self:custom.stageConfig.${self:provider.stage}.wsSqs}
8790
TOTP_KEY: ${env:TOTP_KEY}
8891
VAPID_PRIVATE_KEY: ${env:VAPID_PRIVATE_KEY}
8992
VAPID_PUBLIC_KEY: ${env:VAPID_PUBLIC_KEY}

0 commit comments

Comments
 (0)