Skip to content

Commit

Permalink
implement mongodb persistent storage with express server
Browse files Browse the repository at this point in the history
  • Loading branch information
kajgm committed Nov 3, 2024
1 parent c1e46e9 commit a7955ec
Show file tree
Hide file tree
Showing 18 changed files with 1,485 additions and 132 deletions.
25 changes: 20 additions & 5 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -80,23 +80,32 @@ To deploy within Docker, please follow these steps:

> Tip: Run `sudo usermod -aG docker <user>` to avoid prefixing the following commands with sudo
2. Build the dockerfile within the `/client` directory
2. Create the `.env` files from the templates in `/client` and `/server`

3. Build the dockerfile within the `/client` directory

```sh
docker build -t kajgm/stocktracker-client .
```

3. Build the dockerfile within the `/server` directory
4. Build the dockerfile within the `/server` directory

```sh
docker build -t kajgm/stocktracker-server .
```

4. Run the client and server containers
5. Create a network for these containers

```sh
docker network create -d bridge backend-net
```

6. Run the client, server, and database containers

```sh
docker run -d -p 8080:80 --name stocktracker-client --restart always kajgm/stocktracker-client
docker run -d -p 3000:3000 --name stocktracker-server --restart always kajgm/stocktracker-server
docker run -d -p 8080:80 --name stocktracker-client --network backend-net --restart always kajgm/stocktracker-client
docker run -d -p 3000:3000 --name stocktracker-server --network backend-net --env-file=./.env --restart always kajgm/stocktracker-server
docker run -d --name mongodb-server --network backend-net -v stocktracker:/data/db --restart always mongo
```

## Deployment on Raspberry Pi
Expand Down Expand Up @@ -129,3 +138,9 @@ chromium-browser --kiosk --app=http://localhost:8080/ --start-fullscreen --incog
```sh
nohup chromium-browser --kiosk --app=http://localhost:8080/ --start-fullscreen --incognito &
```

As an alternative, a startup script has been provided in the root directory `./startup`. Ensure that the script is executable before running or referencing in any automated startup routine.

```sh
chmod +x <username>
```
1 change: 1 addition & 0 deletions client/.env.template
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
FMP_KEY="<your_api_key>"
EXPRESS_URI="http://localhost:3000/api/get/tickers"
2 changes: 1 addition & 1 deletion client/src/components/ticker/TickerBox.vue
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ const sInfo = SizeMap[boxSize];
<template>
<div class="p-1.5 w-full h-full">
<div class="bg-zinc-800 rounded-2xl w-full h-full overflow-hidden">
<RouterLink :id="ticker.id" :to="rLink">
<RouterLink :id="ticker.id" :ticker-type="tickerType" :to="rLink">
<div class="p-2 h-full w-full flex flex-wrap flex-col">
<h1 class="font-medium" :class="sInfo.name">{{ ticker.id }}</h1>
<div v-if="ticker.status == 'CONNECTING'">
Expand Down
8 changes: 6 additions & 2 deletions client/src/server/server.ts
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
import axios from 'axios';
import { useTickerStore } from '@/store/ticker.js';
import { coinbaseConnect } from '@/crypto/crypto.js';
import { fmpQuery } from '@/stock/stock.js';

const SERVER_TIMEOUT = 1000;
const SERVER_ENDPOINT = 'http://localhost:3000/api/get/tickers';

export function getUpdatedTickers() {
const tickerStore = useTickerStore();
let cryptoUpdatedFlag = false;
let stockUpdatedFlag = false;
axios
.get(SERVER_ENDPOINT)
.get(process.env.EXPRESS_URI!)
.then((res) => {
// eslint-disable-next-line @typescript-eslint/no-unsafe-call, @typescript-eslint/no-unsafe-member-access
const cryptoTcks = res.data['cryptoTickers'] as string;
Expand Down Expand Up @@ -63,5 +63,9 @@ export function pollUpdatedTickers() {
tickerStore.setSocket(newSocket);
}

if (tickerStore.stockStatus == 'UPDATED') {
fmpQuery();
}

setTimeout(pollUpdatedTickers, SERVER_TIMEOUT);
}
10 changes: 5 additions & 5 deletions client/src/stock/stock.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,16 +15,13 @@ const STOCK_ENDPOINT = 'https://financialmodelingprep.com/api/v3/quote/';
const openHours = 570; // 9 * 60 + 30
const closeHours = 960; // 16 * 60

export function fmpConnect() {
export function fmpQuery() {
const tickerStore = useTickerStore();
const date = new Date();
const currentTime = (date.getUTCHours() - 4) * 60 + date.getUTCMinutes();
const isWeekday = date.getDay() % 6 != 0;

if (
(openHours <= currentTime && currentTime <= closeHours && isWeekday) ||
(tickerStore.stockStatus != 'CONNECTED' && tickerStore.stockKeys.length > 0)
) {
if ((openHours <= currentTime && currentTime <= closeHours && isWeekday) || tickerStore.stockKeys.length > 0) {
axios
.get(STOCK_ENDPOINT + tickerStore.stockKeys.toString() + '?apikey=' + process.env.FMP_KEY)
.then((res) => {
Expand Down Expand Up @@ -58,6 +55,9 @@ export function fmpConnect() {
} else {
console.log('Skipped api call, outside trading hours or no stocks provided');
}
}

export function fmpConnect() {
fmpQuery();
setTimeout(fmpConnect, API_TIMEOUT);
}
13 changes: 4 additions & 9 deletions client/src/views/Chart.vue
Original file line number Diff line number Diff line change
@@ -1,22 +1,17 @@
<script setup lang="ts">
import { useTickerStore } from '@/store/ticker';
import { computed } from 'vue';
import type { TickerData, SizeType } from '@/types/types';
import type { SizeType } from '@/types/types';
import TickerBox from '@/components/ticker/TickerBox.vue';
const { tickerId } = defineProps<{
const { tickerId, tickerType } = defineProps<{
tickerId: string;
tickerType: string;
}>();
const tickerStore = useTickerStore();
const ticker = computed<TickerData>(() => {
return tickerStore.tickerValue(tickerId);
});
const boxSize = 'LARGE' as SizeType;
</script>

<template>
<div class="flex flex-wrap justify-center m-auto w-full h-full">
<TickerBox :ticker-id="ticker.id" :box-size="boxSize" r-link="/"></TickerBox>
<TickerBox :ticker-id="tickerId" :ticker-type="tickerType" :box-size="boxSize" r-link="/"></TickerBox>
</div>
</template>
2 changes: 0 additions & 2 deletions client/src/views/TickerGrid.vue
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@ import { useTickerStore } from '@/store/ticker';
import { type SizeType } from '@/types/types';
import TickerBox from '@/components/ticker/TickerBox.vue';
const appVersion = process.env.appVersion;
const tickerStore = useTickerStore();
const cryptoIds = computed<string[]>(() => {
return tickerStore.cryptoKeys;
Expand All @@ -20,7 +19,6 @@ const boxSize = 'SMALL' as SizeType;
<h1 class="font-medium text-4xl">Connecting...</h1>
</div>
<div v-else-if="tickerStore.status.overall == 'CONNECTED'" class="flex flex-wrap justify-center m-auto w-full h-full">
<div class="absolute left-[calc(50%-16px)] top-[calc(50%-8px)] text-xs text-zinc-600">v{{ appVersion }}</div>
<div v-for="id in cryptoIds" :key="id" class="w-1/2 h-1/2">
<TickerBox :ticker-id="id" ticker-type="CRYPTO" :box-size="boxSize" :r-link="id"></TickerBox>
</div>
Expand Down
11 changes: 1 addition & 10 deletions client/vite.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,18 +2,9 @@ import vue from '@vitejs/plugin-vue';
import EnvironmentPlugin from 'vite-plugin-environment';
import { defineConfig } from 'vite';
import { resolve } from 'path';
import { version } from './package.json';

export default defineConfig({
plugins: [
vue(),
EnvironmentPlugin({
FMP_KEY: null,
STOCK_TICKERS: 'MSFT,AAPL,NVDA,AMD,INTC,AMZN',
CRYPTO_TICKERS: 'ETH-USD,BTC-USD',
appVersion: version
})
],
plugins: [vue(), EnvironmentPlugin('all', { prefix: '' })],
resolve: {
alias: {
'@': resolve(__dirname, 'src'),
Expand Down
2 changes: 2 additions & 0 deletions server/.env.template
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
PORT=3000
MONGO_URI=mongodb://mongodb-server/stocktracker
9 changes: 9 additions & 0 deletions server/.prettierrc.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/prettierrc",
"semi": true,
"tabWidth": 2,
"singleQuote": true,
"printWidth": 120,
"endOfLine": "auto",
"trailingComma": "none"
}
15 changes: 15 additions & 0 deletions server/config/db.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
import mongoose from 'mongoose';

const MONGO_URI = process.env.MONGO_URI || 'mongodb://localhost:27017/stocktracker';

const connectDB = async () => {
try {
await mongoose.connect(MONGO_URI);
console.log('MongoDB is connected');
} catch (e) {
console.log(e);
process.exit(1);
}
};

export default connectDB;
18 changes: 18 additions & 0 deletions server/models/Tickers.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
import { Schema, model } from 'mongoose';

const cryptoSchema = new Schema({
crypto: {
type: String,
required: true
}
});

const stockSchema = new Schema({
stock: {
type: String,
required: true
}
});

export const Cryptos = model('Cryptos', cryptoSchema);
export const Stocks = model('Stocks', stockSchema);
Loading

0 comments on commit a7955ec

Please sign in to comment.