this is podracing

This commit is contained in:
ntr committed 2022-09-04 20:36:42 +10:00
1 parent 65d37eeb61
commit f2294def05
12 files changed
+187 -169

No files matched your search

+9 -9
View File
@@ -5,15 +5,15 @@ import { Events } from './src/events';
async function start() { async function start() {
const log = createLog(); const log = createLog();
process.on('uncaughtException', (err, origin) => { // process.on('uncaughtException', (err, origin) => {
log.error({ err, origin }, 'uncaughtException'); // log.error({ err, origin }, 'uncaughtException');
process.exit(1); // process.exit(1);
}); // });
process.on('unhandledRejection', (reason, promise) => { // process.on('unhandledRejection', (reason, promise) => {
log.error({ reason, promise }, 'unhandledRejection'); // log.error({ reason, promise }, 'unhandledRejection');
process.exit(1); // process.exit(1);
}); // });
process.on('SIGTERM', () => { process.on('SIGTERM', () => {
log.debug('SIGTERM received, exiting'); log.debug('SIGTERM received, exiting');
@@ -31,7 +31,7 @@ async function start() {
// events.emit(Events.StartupSync); // events.emit(Events.StartupSync);
// events.emit(Events.ListingsUpdated); // events.emit(Events.ListingsUpdated);
await api.listen(); api.listen();
} }
start(); start();
+11
View File
@@ -16,6 +16,7 @@
"bluebird": "^3.7.2", "bluebird": "^3.7.2",
"bunyan": "^1.8.15", "bunyan": "^1.8.15",
"cheerio": "^1.0.0-rc.12", "cheerio": "^1.0.0-rc.12",
"json-rpc-2.0": "^1.4.1",
"koa": "^2.13.4", "koa": "^2.13.4",
"koa-body": "^5.0.0", "koa-body": "^5.0.0",
"koa-passport": "^5.0.0", "koa-passport": "^5.0.0",
@@ -1872,6 +1873,11 @@
"js-yaml": "bin/js-yaml.js" "js-yaml": "bin/js-yaml.js"
} }
}, },
"node_modules/json-rpc-2.0": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.4.1.tgz",
"integrity": "sha512-OX1NJhpIfuK4GjDnJ/gKtZy1HOYo0l4eL0a4rb0rNeQheX1xlyQ9+JMmPzs/sFNthpS/TXKPWlGo09X7B5l81A=="
},
"node_modules/keygrip": { "node_modules/keygrip": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
@@ -5094,6 +5100,11 @@
"argparse": "^2.0.1" "argparse": "^2.0.1"
} }
}, },
"json-rpc-2.0": {
"version": "1.4.1",
"resolved": "https://registry.npmjs.org/json-rpc-2.0/-/json-rpc-2.0-1.4.1.tgz",
"integrity": "sha512-OX1NJhpIfuK4GjDnJ/gKtZy1HOYo0l4eL0a4rb0rNeQheX1xlyQ9+JMmPzs/sFNthpS/TXKPWlGo09X7B5l81A=="
},
"keygrip": { "keygrip": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz", "resolved": "https://registry.npmjs.org/keygrip/-/keygrip-1.1.0.tgz",
+3 -2
View File
@@ -13,12 +13,13 @@ const api = axios.create({
withCredentials: true withCredentials: true
}); });
let server;
before(function setup() { before(function setup() {
services.api.listen(); server = services.api.listen();
}); });
after(function teardown(done) { after(function teardown(done) {
services.api.server.close(done) server.close(done)
}); });
describe('api', function apiTests() { describe('api', function apiTests() {
+27 -33
View File
@@ -22,10 +22,7 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
const WS_PORT = 40055; const WS_PORT = 40055;
const SECRET = 'ohja4Eif9eidah3aj5ta2haa4iemooth'; const SECRET = 'ohja4Eif9eidah3aj5ta2haa4iemooth';
const app = new koa(); const app = koaWebsocket(new koa());
const server = http.createServer(app.callback());
const wsApp = koaWebsocket(new koa());
const wsServer = http.createServer(wsApp.callback());
app.use(async (ctx, next) => { app.use(async (ctx, next) => {
try { try {
@@ -42,18 +39,8 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
const router = koaRouter(); const router = koaRouter();
function listen() { function listen() {
return new Promise((resolve, reject) => { const server = app.listen(PORT);
app.on('error', err => { log.info({ PORT }, 'listening');
reject(err);
})
server.listen(PORT, () => {
log.info('listening', { PORT });
});
wsApp.listen(WS_PORT);
log.info('ws listening', { WS_PORT });
});
} }
app.use(cors({ credentials: true })); app.use(cors({ credentials: true }));
@@ -160,27 +147,34 @@ export default function createApi(log: Log, pg: Pg, discogs, offers, events) {
ctx.body = { success: true }; ctx.body = { success: true };
}); });
const wsRouter = koaRouter();
// Using routes
wsRouter.get('/ws', async (ctx, next) => {
// `ctx` is the regular koa context created from the `ws` onConnection `socket.upgradeReq` object.
// the websocket is added to the context on `ctx.websocket`.
ctx.websocket.send('Hello World');
ctx.websocket.on('message', (message) => {
// do something with the message from client
if (message.toString() === 'ping') {
ctx.websocket.send('pong');
}
});
return next;
});
app.use(router.routes()); app.use(router.routes());
wsApp.ws.use(wsRouter.routes());
app.ws.use(passport.initialize());
app.ws.use(passport.session());
app.ws.use(async (ctx, next) => {
log.info('new ws connection', { user: ctx.state.user });
ctx.websocket.on('message', async function incoming(message) {
log.info(message.toString());
try {
const parsed = JSON.parse(message.toString());
log.info(parsed);
// const response = await rpc.receive(parsed);
// rpc.send(ws, response);
} catch (e) {
log.warn(e);
log.warn(message.toString());
// rpc.send(ws, [RpcMessageType.Error, e.message || e.msg])
}
return true;
});
ctx.websocket.on('close', function onClose() {
log.info('ws disconnected', { user: ctx.state.user });
});
});
return { return {
app, app,
server,
listen, listen,
}; };
} }
+31
View File
@@ -0,0 +1,31 @@
module.exports = {
parser: "@typescript-eslint/parser",
extends: [
"preact",
"plugin:@typescript-eslint/recommended"
],
ignorePatterns: [
"build/"
],
rules: {
// prevents stupid complaints a la
// (req) {
// req.something = x;
// }
'no-param-reassign': [2, { props: false }],
'no-multi-spaces': [0],
'max-len': ['error', 120],
'import/no-extraneous-dependencies': [0],
'prefer-arrow-callback': [0],
'arrow-body-style': [0],
'no-return-assign': 0,
'no-console': [0],
// i like loops
'no-plusplus': [0],
'no-await-in-loop': [0],
indent: ['error', 4],
'keyword-spacing': ['error'],
'key-spacing': ['error'],
},
};
-10
View File
@@ -8,16 +8,6 @@
"start": "preact --no-clear watch", "start": "preact --no-clear watch",
"lint": "eslint src" "lint": "eslint src"
}, },
"eslintConfig": {
"parser": "@typescript-eslint/parser",
"extends": [
"preact",
"plugin:@typescript-eslint/recommended"
],
"ignorePatterns": [
"build/"
]
},
"dependencies": { "dependencies": {
"lodash": "^4.17.21", "lodash": "^4.17.21",
"preact": "^10.10.0", "preact": "^10.10.0",
@@ -1,3 +1,6 @@
import { route } from 'preact-router';
import http from './http';
const actions = store => ({ const actions = store => ({
setUser: function setUser(state, user) { setUser: function setUser(state, user) {
return { user }; return { user };
@@ -7,7 +10,7 @@ const actions = store => ({
return { offers }; return { offers };
}, },
logout: async function logout(store, e) { logout: async function logout() {
await http.postLogout(); await http.postLogout();
route('/login'); route('/login');
return { user: null }; return { user: null };
+1
View File
@@ -51,4 +51,5 @@ const Header = ({ user, logout }) => {
); );
} }
// @ts-ignore unistore types
export default connect(['user'], actions)(Header); export default connect(['user'], actions)(Header);
-3
View File
@@ -1,8 +1,5 @@
import { route } from 'preact-router';
import unistore from 'unistore' import unistore from 'unistore'
import http from './http';
export default function createStore() { export default function createStore() {
return unistore({ return unistore({
bundles: [], bundles: [],
+99 -103
View File
@@ -1,117 +1,113 @@
// const SOCKET_URL = (window.location.host.includes('localhost') || window.location.host === '' || window.location.host.includes('192.168.0'))
// ? `ws://${window.location.hostname}:40080`
// : `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`;
const SOCKET_URL = `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`; const SOCKET_URL = `${window.location.protocol === 'https:' ? 'wss://' : 'ws://'}${window.location.host}/api/ws`;
export default function createSocket(store) { export default function createSocket(store) {
let ws; let ws;
// ------------- // -------------
// Outgoing // Outgoing
// ------------- // -------------
function send(msg) { function send(msg) {
if (msg[0] !== 'Ping') console.log('outgoing msg', msg); if (msg[0] !== 'Ping') console.log('outgoing msg', msg);
if (ws.readyState !== 1) return false; if (ws.readyState !== 1) return false;
try { try {
ws.send(JSON.stringify(msg)); ws.send(JSON.stringify(msg));
} catch (e) { } catch (e) {
console.warn(e); console.warn(e);
} }
}
// let ping;
function sendPing() {
// ping = Date.now();
send(['Ping', {}]);
// setTimeout(sendPing, 50);
}
function sendSourcesAvailable() {
send(['SourcesAvailable', {}]);
}
let pongTimeout;
function onPong() {
pongTimeout = setTimeout(sendPing, 1000);
}
// -------------
// Incoming
// -------------
function onSourcesAvailable(clouds) {
// store.dispatch(http.LIBRARY_RECEIVE_POINTCLOUDS, clouds);
}
// -------------
// Setup
// -------------
// when the server sends a reply it will have one of these message types
// this object wraps the reply types to a function
const handlers = {
SourcesAvailable: onSourcesAvailable,
Pong: onPong,
Error: errHandler,
};
function errHandler(error) {
// store.dispatch(http.LIBRARY_EVENT, { level: 'error', log: error });
console.error(error);
}
function onMessage(event) {
const res = event.data;
const [msgType, params] = JSON.parse(res);
if (msgType !== 'Pong') {
console.log(msgType, params);
} }
// check for error and split into response type and data // let ping;
if (!handlers[msgType]) return console.error(`${msgType} handler missing`); function sendPing() {
return handlers[msgType](params); // ping = Date.now();
} send(['Ping', {}]);
// Connection opened // setTimeout(sendPing, 50);
function onOpen() {
sendPing();
}
function onError(event) {
console.error('WebSocket error', event);
}
function onClose(event) {
console.error('WebSocket closed', event);
return setTimeout(connect, 2000);
}
function connect() {
if (ws) {
clearTimeout(pongTimeout);
ws.removeEventListener('open', onOpen);
ws.removeEventListener('message', onMessage);
ws.removeEventListener('error', onError);
ws.removeEventListener('close', onClose);
ws = null;
} }
console.log('connecting to websocket', SOCKET_URL); function sendSourcesAvailable() {
ws = new WebSocket(SOCKET_URL); send(['SourcesAvailable', {}]);
}
// Listen for messages let pongTimeout;
ws.addEventListener('open', onOpen); function onPong() {
ws.addEventListener('message', onMessage); pongTimeout = setTimeout(sendPing, 1000);
ws.addEventListener('error', onError); }
ws.addEventListener('close', onClose);
return ws; // -------------
} // Incoming
// -------------
function onSourcesAvailable(clouds) {
// store.dispatch(http.LIBRARY_RECEIVE_POINTCLOUDS, clouds);
}
return { // -------------
connect, // Setup
// -------------
// when the server sends a reply it will have one of these message types
// this object wraps the reply types to a function
const handlers = {
SourcesAvailable: onSourcesAvailable,
sendSourcesAvailable, Pong: onPong,
}; Error: errHandler,
};
function errHandler(error) {
// store.dispatch(http.LIBRARY_EVENT, { level: 'error', log: error });
console.error(error);
}
function onMessage(event) {
const res = event.data;
const [msgType, params] = JSON.parse(res);
if (msgType !== 'Pong') {
console.log(msgType, params);
}
// check for error and split into response type and data
if (!handlers[msgType]) return console.error(`${msgType} handler missing`);
return handlers[msgType](params);
}
// Connection opened
function onOpen() {
sendPing();
}
function onError(event) {
console.error('WebSocket error', event);
}
function onClose(event) {
console.error('WebSocket closed', event);
return setTimeout(connect, 2000);
}
function connect() {
if (ws) {
clearTimeout(pongTimeout);
ws.removeEventListener('open', onOpen);
ws.removeEventListener('message', onMessage);
ws.removeEventListener('error', onError);
ws.removeEventListener('close', onClose);
ws = null;
}
console.log('connecting to websocket', SOCKET_URL);
ws = new WebSocket(SOCKET_URL);
// Listen for messages
ws.addEventListener('open', onOpen);
ws.addEventListener('message', onMessage);
ws.addEventListener('error', onError);
ws.addEventListener('close', onClose);
return ws;
}
return {
connect,
sendSourcesAvailable,
};
} }
-3
View File
@@ -22,9 +22,6 @@ services:
DATABASE_URL: 'postgresql://mcrates:digdeep@pg:5432/mcrates?schema=public' DATABASE_URL: 'postgresql://mcrates:digdeep@pg:5432/mcrates?schema=public'
volumes: volumes:
- "./api:/opt/mcrates/api" - "./api:/opt/mcrates/api"
ports:
- '41337:41337'
- '40055:40055'
client: client:
image: node:16 image: node:16
+2 -5
View File
@@ -2,10 +2,6 @@ upstream mcrates_api {
server api:41337; server api:41337;
} }
upstream mcrates_ws {
server api:40055;
}
upstream mcrates_client { upstream mcrates_client {
server client:8080; server client:8080;
} }
@@ -22,10 +18,11 @@ server {
} }
location /api/ws { location /api/ws {
proxy_pass http://mcrates_ws; proxy_pass http://mcrates_api;
proxy_http_version 1.1; proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade; proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade; proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 600s; proxy_read_timeout 600s;
} }