Skip to content

Commit

Permalink
postgres client pooling + testing insert in server
Browse files Browse the repository at this point in the history
  • Loading branch information
pan261 committed Jan 31, 2022
1 parent 9530282 commit 6a60837
Show file tree
Hide file tree
Showing 9 changed files with 215 additions and 28 deletions.
26 changes: 14 additions & 12 deletions docker-compose.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,23 @@ version: "3.8"

services:

# access through `psql -h localhost -p 5432 -d filesync -U user`, password is 'pass'
# to be able to build after the initializing the db, you may need to run `sudo chown -R $USER db_data/`
database:
image: 'postgres:13'
env_file: ./.env
volumes:
- ./postgres/db_data/:/var/lib/postgresql/data/
- ./postgres/sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
ports:
- ${PORT_DB}:${PORT_DB}

server:
build:
context: .
dockerfile: Dockerfile
depends_on:
- database
env_file: ./.env
volumes:
- ./src/build:/ffs/
Expand All @@ -17,15 +30,4 @@ services:
- ${LOCAL_DIR_WATERJET}:/ffs/file_share/Waterjet/
ports:
- ${PORT_SERVER}:${PORT_SERVER}
command: "node server.js"

# access through `psql -h localhost -p 5432 -d filesync -U user`, password is 'pass'
# to be able to build after the initializing the db, you may need to run `sudo chown -R $USER db_data/`
database:
image: 'postgres:13'
env_file: ./.env
volumes:
- ./postgres/db_data/:/var/lib/postgresql/data/
- ./postgres/sql/create_tables.sql:/docker-entrypoint-initdb.d/create_tables.sql
ports:
- ${PORT_DB}:${PORT_DB}
command: "node server.js"
3 changes: 2 additions & 1 deletion environment.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,8 @@ declare global {
FORGE_CLIENT_ID: string;
FORGE_CLIENT_SECRET: string;
FORGE_CALLBACK_URL: string;
PORT_SERVER: string;
PORT_SERVER: number;
PORT_DB: number;
WEBHOOK_TOKEN: string;
}
}
Expand Down
46 changes: 45 additions & 1 deletion package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 3 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,9 @@
"crypto": "^1.0.1",
"dotenv": "^10.0.0",
"express": "^4.17.1",
"forge-apis": "^0.8.6"
"forge-apis": "^0.8.6",
"generic-pool": "^3.8.2",
"ts-postgres": "^1.2.1"
},
"devDependencies": {
"@types/dotenv": "^8.2.0",
Expand Down
22 changes: 14 additions & 8 deletions postgres/sql/create_tables.sql
Original file line number Diff line number Diff line change
@@ -1,23 +1,29 @@
-- Primary keys must include folder name in order to avoid collisions
-- between filenames in different folders

CREATE TABLE IF NOT EXISTS fusion (
fusion_id varchar(250) NOT NULL,
folder_name varchar(250) NOT NULL,
file_name varchar(250) NOT NULL,
username varchar(250) NOT NULL,
size int NOT NULL,
version int NOT NULL,
username varchar(250),
size int,
version int,
PRIMARY KEY (fusion_id)
);

CREATE TABLE IF NOT EXISTS local (
file_name varchar(250) NOT NULL,
fusion_id varchar(250) NOT NULL,
PRIMARY KEY (file_name)
folder_name varchar(250) NOT NULL,
fusion_id varchar(250),
PRIMARY KEY (file_name, folder_name)
);

CREATE TABLE IF NOT EXISTS archive (
fusion_id varchar(250) NOT NULL,
file_name varchar(250) NOT NULL,
folder_name varchar(250) NOT NULL,
username varchar(250) NOT NULL,
size int NOT NULL,
version int NOT NULL,
PRIMARY KEY (fusion_id)
size int,
version int,
PRIMARY KEY (fusion_id, folder_name)
);
8 changes: 5 additions & 3 deletions src/config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,7 @@
*/

import { AuthClientThreeLegged } from 'forge-apis';

import * as dotenv from 'dotenv';

dotenv.config({path: '../.env'});

export const ForgeAuthClient = AuthClientThreeLegged;
Expand Down Expand Up @@ -58,4 +56,8 @@ export const forgeClientId = process.env.FORGE_CLIENT_ID;
export const forgeClientSecret = process.env.FORGE_CLIENT_SECRET;
export const forgeCallbackURL = process.env.FORGE_CALLBACK_URL;
export const hookCallbackURL = `${process.env.HOOK_CALLBACK_HOSTNAME}/hook`;
export const webhookToken = process.env.WEBHOOK_TOKEN;
export const webhookToken = process.env.WEBHOOK_TOKEN;
export const postgresUser = process.env.POSTGRES_USER;
export const postgresPassword = process.env.POSTGRES_PASSWORD;
export const postgresPort = process.env.PORT_DB;
export const postgresDB = process.env.POSTGRES_DB;
108 changes: 108 additions & 0 deletions src/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { Client, Query } from 'ts-postgres';
import { createPool } from 'generic-pool';
import * as config from './config';

const pool = createPool({
create: async () => {
return new Promise<Client>((resolve, reject) => {

const client = new Client({
'host': 'database', // name of docker container, not 'localhost'
'port': config.postgresPort,
'user': config.postgresUser,
'password': config.postgresPassword,
'database': config.postgresDB
});

client.connect()
.then(() => {
console.log("successfully connected to db")
resolve(client);
}).catch((err) => {
console.log()
console.log(err)
reject(err);
});
});
},
destroy: async (client: Client) => {
return client.end()
},
validate: (client: Client) => {
return Promise.resolve(!client.closed);
}
}, {
testOnBorrow: true,
max: 10
})

const executeQuery = (query: Query) => {
console.log('executing query');

const res = pool.acquire();

return res.then(async (client: Client) => {
console.log('aquired client from pool')
const result = await client.execute(query);
pool.release(client).then(() => {
console.log("client released back into pool")
});
return result;
}).catch(err => {
console.log(err);
})
}

export const shutdown = () => {
pool.drain()
.then(() => {
return pool.clear();
});
}

export const insert = (table: string, params: any) => {

let fileName = params.fileName;
let folderName = params.folderName;
let fusionID = null;
let username = null;
let size = null;
let version = null;

if (params.hasOwnProperty('fusionID')) {fusionID = params.fusionID}
if (params.hasOwnProperty('username')) {username = params.username}
if (params.hasOwnProperty('size')) {size = params.size}
if (params.hasOwnProperty('version')) {version = params.version}

let query: Query;

console.log("params: ", params);

switch(table) {
case 'fusion':
query = new Query (
"INSERT INTO fusion (fusion_id, folder_name, file_name, username, size, version)" +
"VALUES ($1, $2, $3, $4, $5, $6)",
[fusionID, folderName, fileName, username, size, version]
);
break;
case 'local':
query = new Query (
"INSERT INTO local (file_name, folder_name, fusion_id)" +
"VALUES ($1, $2, $3)",
[fileName, folderName, fusionID]
);
break;
case 'archive':
query = new Query (
"INSERT INTO archive (fusion_id, folder_name, file_name, username, size, version)" +
"VALUES ($1, $2, $3, $4, $5, $6)",
[fusionID, folderName, fileName, username, size, version]
);
break;
default:
throw new Error("Invalid table/params");
}

return executeQuery(query);
}
2 changes: 1 addition & 1 deletion src/old/watcher.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// const axios = require('axios');
const axios = require('axios');

/**
* Kevin Pan | pan261@purdue.edu | Last Modified: 12/2/2021
Expand Down
24 changes: 23 additions & 1 deletion src/server.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ import express = require('express');
import bodyParser = require('body-parser');
import crypto = require('crypto');
import * as config from './config';
import * as db from './db';
import fs = require('fs');

const webhooks = require('./webhooks');
Expand Down Expand Up @@ -149,6 +150,15 @@ const createServer = () => {
}
});

// Will make some server endpoints to test db
app.get('/db/insert', async function (req: any, res: any) {
const result = await db.insert("local", {
fileName: crypto.randomBytes(10).toString('hex'),
folderName: 'Mill',
});
res.send(result);
});

// Default endpoint
app.use((err: any, req: any, res: any, next: any) => {
console.error(err);
Expand Down Expand Up @@ -181,4 +191,16 @@ const refresh = () => {
});
};

createServer();
const server = createServer();

/**
* May eventually need this to drain db connection pool
* With docker, ctrl+c doesn't work (apparently it is not a SIGINT),
* need to open a new terminal and run `docker-compose stop`
*/
process.on('SIGTERM', async () => {
console.log("shutting down node process")
await db.shutdown();
if (server) {server.close()}
process.exit(0)
});

0 comments on commit 6a60837

Please sign in to comment.