Skip to content

Commit

Permalink
Merge pull request #55 from VedalAI/db-model
Browse files Browse the repository at this point in the history
improve db model
  • Loading branch information
Govorunb authored Jul 9, 2024
2 parents 535b9a6 + 4cfb860 commit a9655a1
Show file tree
Hide file tree
Showing 23 changed files with 909 additions and 615 deletions.
38 changes: 34 additions & 4 deletions common/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ export const enum LiteralTypes {
Integer,
Float,
Boolean,
Vector
Vector,
}

type EnumTypeName = string;
Expand Down Expand Up @@ -56,7 +56,7 @@ export type Redeem = {
args: Parameter[];
announce?: boolean;
moderated?: boolean;

image: string;
price: number;
sku: string;
Expand All @@ -68,7 +68,6 @@ export type Config = {
version: number;
enums?: { [name: string]: string[] };
redeems?: { [id: string]: Redeem };
banned?: string[];
message?: string;
};

Expand All @@ -89,13 +88,44 @@ export type Transaction = {
};

export type PubSubMessage = {
type: string;
type: "config_refreshed" | "banned";
data: string;
};

export type BannedData = {
id: string;
banned: boolean;
};

export type LogMessage = {
transactionToken: string | null;
userIdInsecure: string | null;
important: boolean;
fields: { header: string; content: any }[];
};

export type User = {
id: string;
login?: string;
displayName?: string;
banned: boolean;
};

export type OrderState =
| "rejected"
| "prepurchase"
| "cancelled"
| "paid" // waiting for game
| "failed" // game failed/timed out
| "succeeded";

export type Order = {
id: string;
userId: string;
state: OrderState;
cart?: Cart;
receipt?: string;
result?: string;
createdAt: number;
updatedAt: number;
};
1 change: 1 addition & 0 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ services:
MYSQL_PASSWORD: ebs
volumes:
- ./_volumes/db:/var/lib/mysql
- ./scripts/sql/init_db.sql:/docker-entrypoint-initdb.d/init_db.sql

nginx-proxy:
image: nginxproxy/nginx-proxy:latest
Expand Down
12 changes: 5 additions & 7 deletions ebs/src/index.ts
Original file line number Diff line number Diff line change
@@ -1,20 +1,18 @@
import { config as dotenv } from "dotenv";
import "dotenv/config";
import cors from "cors";
import express from "express";
import expressWs from "express-ws";
import bodyParser from "body-parser";
import { privateApiAuth, publicApiAuth } from "./util/middleware";
import { asyncCatch, privateApiAuth, publicApiAuth } from "./util/middleware";
import { initDb } from "./util/db";
import { sendToLogger } from "./util/logger";

dotenv();

const port = 3000;

export const { app } = expressWs(express());
app.use(cors({ origin: "*" }));
app.use(bodyParser.json());
app.use("/public/*", publicApiAuth);
app.use("/public/*", asyncCatch(publicApiAuth));
app.use("/private/*", privateApiAuth);

app.get("/", (_, res) => {
Expand All @@ -28,7 +26,7 @@ async function main() {
console.log("Listening on port " + port);

require("./modules/config");
require("./modules/transactions");
require("./modules/orders");
require("./modules/game");
require("./modules/twitch");

Expand Down Expand Up @@ -82,4 +80,4 @@ async function main() {
});
}

main().catch(console.error);
main().catch(console.error);
9 changes: 0 additions & 9 deletions ebs/src/modules/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { Config } from "common/types";
import { app } from "..";
import { sendPubSubMessage } from "../util/pubsub";
import { compressSync, strFromU8, strToU8 } from "fflate";
import { getBannedUsers } from "../util/db";
import { asyncCatch } from "../util/middleware";
import { Webhooks } from "@octokit/webhooks";
import { sendToLogger } from "../util/logger";
Expand All @@ -22,10 +21,6 @@ async function fetchConfig(): Promise<Config> {

const data: Config = JSON.parse(atob(responseData.content))

console.log(data);

data.banned = await getBannedUsers();

return data;
} catch (e: any) {
console.error("Error when fetching config from api URL, falling back to raw URL");
Expand All @@ -48,10 +43,6 @@ async function fetchConfig(): Promise<Config> {
const response = await fetch(url);
const data: Config = await response.json();

console.log(data)

data.banned = await getBannedUsers();

return data;
} catch (e: any) {
console.error("Error when fetching config from raw URL, panic");
Expand Down
76 changes: 47 additions & 29 deletions ebs/src/modules/game/connection.ts
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import { Message, MessageType, TwitchUser } from "./messages";
import { ResultMessage, GameMessage } from "./messages.game";
import { GameMessage, ResultMessage } from "./messages.game";
import * as ServerWS from "ws";
import { v4 as uuid } from "uuid";
import { CommandInvocationSource, RedeemMessage, ServerMessage } from "./messages.server";
import { Cart, Redeem } from "common/types";
import { Redeem, Order } from "common/types";
import { setIngame } from "../config";

const VERSION = "0.1.0";
Expand Down Expand Up @@ -34,7 +34,7 @@ export class GameConnection {
console.log("Connected to game");
this.handshake = false;
this.resendIntervalHandle = +setInterval(() => this.tryResendFromQueue(), this.resendInterval);
ws.on('message', async (message) => {
ws.on("message", async (message) => {
const msgText = message.toString();
let msg: GameMessage;
try {
Expand All @@ -43,21 +43,20 @@ export class GameConnection {
console.error("Could not parse message" + msgText);
return;
}
if (msg.messageType !== MessageType.Ping)
console.log(`Got message ${JSON.stringify(msg)}`);
if (msg.messageType !== MessageType.Ping) console.log(`Got message ${JSON.stringify(msg)}`);
this.processMessage(msg);
});
ws.on("close", (code, reason) => {
const reasonStr = reason ? `reason '${reason}'` : "no reason"
const reasonStr = reason ? `reason '${reason}'` : "no reason";
console.log(`Game socket closed with code ${code} and ${reasonStr}`);
setIngame(false);
if (this.resendIntervalHandle) {
clearInterval(this.resendIntervalHandle);
}
})
});
ws.on("error", (error) => {
console.log(`Game socket error\n${error}`);
})
});
}
public processMessage(msg: GameMessage) {
switch (msg.messageType) {
Expand All @@ -66,11 +65,15 @@ export class GameConnection {
const reply = {
...this.makeMessage(MessageType.HelloBack),
allowed: msg.version == VERSION,
}
this.sendMessage(reply).then().catch(e => e);
};
this.sendMessage(reply)
.then()
.catch((e) => e);
break;
case MessageType.Ping:
this.sendMessage(this.makeMessage(MessageType.Pong)).then().catch(e => e);
this.sendMessage(this.makeMessage(MessageType.Pong))
.then()
.catch((e) => e);
break;
case MessageType.Result:
if (!this.outstandingRedeems.has(msg.guid)) {
Expand Down Expand Up @@ -116,8 +119,7 @@ export class GameConnection {
reject(err);
return;
}
if (msg.messageType !== MessageType.Pong)
console.debug(`Sent message ${JSON.stringify(msg)}`);
if (msg.messageType !== MessageType.Pong) console.debug(`Sent message ${JSON.stringify(msg)}`);
resolve();
});
});
Expand All @@ -126,37 +128,39 @@ export class GameConnection {
return {
messageType: type,
guid: guid ?? uuid(),
timestamp: Date.now()
}
timestamp: Date.now(),
};
}
public redeem(redeem: Redeem, cart: Cart, user: TwitchUser, transactionId: string) : Promise<ResultMessage> {
public redeem(redeem: Redeem, order: Order, user: TwitchUser): Promise<ResultMessage> {
return Promise.race([
new Promise<any>((_, reject) => setTimeout(() => reject(`Timed out waiting for result. The redeem may still go through later, contact Alexejhero if it doesn't.`), GameConnection.resultWaitTimeout)),
new Promise<any>((_, reject) =>
setTimeout(
() => reject(`Timed out waiting for result. The redeem may still go through later, contact AlexejheroDev if it doesn't.`),
GameConnection.resultWaitTimeout
)
),
new Promise<ResultMessage>((resolve, reject) => {
if (!transactionId) {
reject(`Tried to redeem without transaction ID`);
return;
}

const msg: RedeemMessage = {
...this.makeMessage(MessageType.Redeem),
guid: transactionId,
guid: order.id,
source: CommandInvocationSource.Swarm,
command: redeem.id,
title: redeem.title,
announce: redeem.announce ?? true,
args: cart.args,
user
args: order.cart!.args,
user,
} as RedeemMessage;
if (this.outstandingRedeems.has(msg.guid)) {
reject(`Redeeming ${msg.guid} more than once`);
return;
}
this.outstandingRedeems.set(msg.guid, msg);
this.resultHandlers.set(msg.guid, resolve);

this.sendMessage(msg).then().catch(e => e); // will get queued to re-send later
})

this.sendMessage(msg)
.then()
.catch((e) => e); // will get queued to re-send later
}),
]);
}

Expand All @@ -178,7 +182,9 @@ export class GameConnection {
}

console.log(`Re-sending message ${JSON.stringify(msg)}`);
this.sendMessage(msg).then().catch(e => e);
this.sendMessage(msg)
.then()
.catch((e) => e);
}
public stressTestSetHandshake(handshake: boolean) {
this.handshake = handshake;
Expand All @@ -190,4 +196,16 @@ export class GameConnection {
public getOutstanding() {
return Array.from(this.outstandingRedeems.values());
}

public onResult(guid: string, resolve: (result: ResultMessage) => void) {
const existing = this.resultHandlers.get(guid);
if (existing) {
this.resultHandlers.set(guid, (result: ResultMessage) => {
existing(result);
resolve(result);
});
} else {
this.resultHandlers.set(guid, resolve);
}
}
}
Loading

0 comments on commit a9655a1

Please sign in to comment.