Skip to content

Commit bdcb754

Browse files
committed
Added tests.
1 parent 54bb457 commit bdcb754

7 files changed

+5492
-351
lines changed

.gitignore

+3
Original file line numberDiff line numberDiff line change
@@ -2,3 +2,6 @@ node_modules/*
22
dirty.db
33
/settings.json
44
.idea
5+
/test1
6+
/test2
7+
/test3

app.ts

+4-142
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,11 @@
1-
'use strict';
2-
3-
import httpProxy from 'http-proxy';
4-
import http from 'http';
5-
import {Database} from 'ueberdb2';
6-
import {checkAvailability} from './checkAvailability.ts'
71
import fs from 'fs'
2+
import {start} from './runtime'
83
// load the settings
94
const loadSettings = () => {
105
let settings;
116
try {
12-
settings = fs.readFileSync('settings.json', 'utf8');
7+
const settings_location = process.env["SETTINGS_FILE"] || "settings.json"
8+
settings = fs.readFileSync(settings_location, 'utf8');
139
return JSON.parse(settings);
1410
} catch (e) {
1511
console.error('Please create your own settings.json file');
@@ -19,138 +15,4 @@ const loadSettings = () => {
1915
};
2016

2117
const settings = loadSettings();
22-
console.debug(settings);
23-
if (settings.dbType === 'dirty') console.error('DirtyDB is not recommend for production');
24-
25-
const backendIds = Object.keys(settings.backends);
26-
27-
// An object of our proxy instances
28-
const proxies: { [key: string]: httpProxy<http.IncomingMessage, http.ServerResponse<http.IncomingMessage>> } = {};
29-
30-
// Making availableBackend globally available.
31-
let availableBackends: {
32-
up: Array<string>,
33-
available: Array<string>,
34-
};
35-
(async () => {
36-
checkAvailability(
37-
settings.backends,
38-
settings.checkInterval,
39-
settings.maxPadsPerInstance);
40-
})();
41-
// And now grab them every X duration
42-
setInterval(async () => {
43-
availableBackends = await checkAvailability(
44-
settings.backends,
45-
settings.checkInterval,
46-
settings.maxPadsPerInstance);
47-
}, settings.checkInterval);
48-
49-
// Creating our database connection
50-
const db = new Database(settings.dbType, settings.dbSettings);
51-
52-
// Initiate the proxy routes to the backends
53-
const initiateRoute = (backend: string, req:http.IncomingMessage, res: http.ServerResponse, socket:any, head:any) => {
54-
if (res) {
55-
// console.log('backend: ', backend);
56-
if (proxies[backend]) {
57-
proxies[backend].web(req, res,{}, (e) => {
58-
console.error(e);
59-
});
60-
}
61-
}
62-
if (socket && head) {
63-
if (proxies[backend]) {
64-
proxies[backend].ws(req, socket, head, {}, (e) => {
65-
console.error(e);
66-
});
67-
}
68-
}
69-
};
70-
71-
// Create dynamically assigned routes based on padIds and ensure that a route for
72-
// unique padIds are re-used and stuck to a backend -- padId <> backend association.
73-
const createRoute = (padId: string | null, req: any, res:any, socket:any, head:any) => {
74-
// If the route isn't for a specific padID IE it's for a static file
75-
// we can use any of the backends but now let's use the first :)
76-
if (!padId) {
77-
const newBackend = availableBackends.available[
78-
Math.floor(Math.random() * availableBackends.available.length)];
79-
return initiateRoute(newBackend, req, res, socket, head);
80-
}
81-
82-
// pad specific backend required, do we have a backend already?
83-
// @ts-ignore
84-
db.get(`padId:${padId}`, (e, r) => {
85-
if (r && r.backend) {
86-
// console.log(`database hit: ${padId} <> ${r.backend}`);
87-
if (!availableBackends) {
88-
return console.log('Request made during startup.');
89-
}
90-
if (availableBackends.up.indexOf(r.backend) !== -1) {
91-
initiateRoute(r.backend, req, res, socket, head);
92-
} else {
93-
// not available.. actually it might be up but not available..
94-
console.log(`hit backend not available: ${padId} <> ${r.backend}`);
95-
const newBackend = availableBackends.up[
96-
Math.floor(Math.random() * availableBackends.up.length)];
97-
// set and store a new backend
98-
db.set(`padId:${padId}`, {
99-
backend: newBackend,
100-
});
101-
console.log(`creating new association: ${padId} <> ${newBackend}`);
102-
initiateRoute(newBackend, req, res, socket, head);
103-
}
104-
} else {
105-
// if no backend is stored for this pad, create a new connection
106-
console.log(availableBackends);
107-
const newBackend = availableBackends.available[
108-
Math.floor(Math.random() * availableBackends.available.length)];
109-
db.set(`padId:${padId}`, {
110-
backend: newBackend,
111-
});
112-
if (!availableBackends.available) console.log('no available backends!');
113-
console.log(`database miss, initiating new association: ${padId} <> ${newBackend}`);
114-
initiateRoute(newBackend, req, res, socket, head);
115-
}
116-
});
117-
};
118-
119-
db.init();
120-
121-
// Create the backends.
122-
for (const backendId of backendIds) {
123-
/* eslint-disable-next-line new-cap */
124-
proxies[backendId] = httpProxy.createProxyServer({
125-
target: {
126-
host: settings.backends[backendId].host,
127-
port: settings.backends[backendId].port,
128-
},
129-
});
130-
}
131-
// Create the routes for web traffic to those backends.
132-
const proxyServer = http.createServer((req, res) => {
133-
let padId: string | null = null;
134-
if (req.url!.indexOf('/p/') !== -1) {
135-
padId = req.url!.split('/p/')[1].split('?')[0].split('/')[0];
136-
console.log(`initial request to /p/${padId}`);
137-
}
138-
if (padId === null) {
139-
const searchParams = new URLSearchParams(req.url);
140-
padId = searchParams.get('/socket.io/?padId');
141-
}
142-
createRoute(padId as string, req, res, null, null);
143-
});
144-
145-
proxyServer.on('error', (e) => {
146-
console.log('proxyserver error', e);
147-
});
148-
149-
// Create a route for upgrade / websockets
150-
proxyServer.on('upgrade', (req, socket, head) => {
151-
const searchParams = new URLSearchParams(req.url);
152-
const padId = searchParams.get('/socket.io/?padId');
153-
createRoute(padId, req, null, socket, head);
154-
});
155-
156-
proxyServer.listen(settings.port);
18+
start(settings);

package.json

+6-2
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,14 @@
2121
"eslint-plugin-prefer-arrow": "^1.2.3",
2222
"eslint-plugin-promise": "^4.3.1",
2323
"eslint-plugin-you-dont-need-lodash-underscore": "^6.11.0",
24-
"typescript": "^5.7.2"
24+
"typescript": "^5.7.2",
25+
"vitest": "^2.1.6",
26+
"testcontainers": "^10.15.0",
27+
"etherpad-load-test": "^1.0.10"
2528
},
2629
"scripts": {
27-
"start": "node --require tsx/cjs app.ts"
30+
"start": "node --require tsx/cjs app.ts",
31+
"test": "vitest"
2832
},
2933
"repository": {
3034
"type": "git",

0 commit comments

Comments
 (0)