Skip to content

Commit e0ca047

Browse files
committed
chore: hardening and cleanup pass
- Drop .env from Dockerfile, inject via docker-compose env_file, add .env.example, bind Fastify/ports to 127.0.0.1 - Fastify bodyLimit 1KB, requestTimeout 15s, setErrorHandler, empty-body JSON schemas on all POST routes - Shared axios client with 15s timeout (src/services/http.ts) - Type route handlers with FastifyInstance/Request/Reply; await Telegram sends in try/catch; move "D1" to config.alert_zone - Add UNIQUE (report_number) migration and PostgreSQL.createOrIgnore (ON CONFLICT DO NOTHING RETURNING) to prevent duplicate alert inserts - Replace system cron + curl loop with in-process croner scheduler and extract task bodies into src/tasks/; Dockerfile drops cron package, cron.txt, log-dir setup, shell-chained CMD - Graceful shutdown on SIGTERM/SIGINT: stopScheduler -> fastify.close -> database.stop with 10s hard-exit guard - postgresql.ts: pino logger instead of console.log, flatten query() control flow, drop JSON.parse(JSON.stringify), preserve error stack, remove duplicate table-name alias in UPDATE - Fix filename id parsing to replace all underscores with slashes - Fix .mocharc.json spec path and rename src/utilites -> src/utilities
1 parent a1483f1 commit e0ca047

37 files changed

Lines changed: 358 additions & 190 deletions

.env.example

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
TELEGRAM_TOKEN=
2+
TELEGRAM_2_TOKEN=
3+
CHAT_ID=
4+
CHANNEL_ID=
5+
DATABASE_NAME=
6+
DATABASE_HOST=
7+
DATABASE_PROD_HOST=
8+
DATABASE_PORT=
9+
DATABASE_USERNAME=
10+
DATABASE_PASSWORD=
11+
ALERT_ZONE=D1

.mocharc.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
{
22
"require": ["ts-node/register"],
33
"extension": ["ts"],
4-
"spec": "./test/**/*.ts"
4+
"spec": "./tests/**/*.ts"
55
}

Dockerfile

Lines changed: 1 addition & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -1,36 +1,19 @@
11
FROM node:22.15.0
22
WORKDIR /usr/app
33

4-
# Install system dependencies including cron
54
RUN apt-get update && apt-get install -y \
65
curl \
7-
cron \
86
&& rm -rf /var/lib/apt/lists/*
97

108
COPY package.json yarn.lock tsconfig.json ./
119
RUN yarn install --frozen-lockfile
1210

1311
COPY ./src ./src
14-
COPY cron.txt /etc/cron.d/mida-cron
15-
COPY .env ./
1612

1713
RUN yarn dist
1814

19-
# Set up cron job from file
20-
RUN chmod 0644 /etc/cron.d/mida-cron
21-
RUN echo "" >> /etc/cron.d/mida-cron
22-
RUN crontab -r || true
23-
RUN crontab /etc/cron.d/mida-cron
24-
25-
# Create log directory for cron
26-
RUN mkdir -p /var/log/cron
27-
RUN touch /var/log/cron/meteo_alerts.log
28-
RUN touch /var/log/cron/check_pretemp_report.log
29-
RUN touch /var/log/cron/check_estofex_report.log
30-
3115
EXPOSE 3000
3216

3317
ENV NODE_ENV production
3418

35-
# Start cron service and the main application
36-
CMD ["sh", "-c", "cron && node ./dist/src/index.js"]
19+
CMD ["node", "./dist/src/index.js"]

README.md

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,11 +43,20 @@ The application relies on scheduled tasks (crons) to automate the weather monito
4343

4444
### Environment Variables (`.env`)
4545

46-
The project uses a `.env` file for configuration. Required keys include:
46+
The project uses a `.env` file for configuration. Copy `.env.example` to `.env` and fill in the values:
47+
48+
```bash
49+
cp .env.example .env
50+
```
51+
52+
Required keys include:
4753

4854
- PostgreSQL Database credentials (Host, User, Password, DB Name)
4955
- `TELEGRAM_TOKEN`: Telegram Bot token.
5056
- `CHAT_ID`: ID of the Telegram chat or channel where alerts will be sent.
57+
- `ALERT_ZONE`: alert zone code to monitor (default `D1`).
58+
59+
The `.env` file is git-ignored and is injected into the container at runtime via `docker-compose.yml` (`env_file`). It is **not** baked into the Docker image. If credentials leak, rotate the Telegram bot token via [@BotFather](https://t.me/BotFather) and reset the PostgreSQL password.
5160

5261
### Development Setup
5362

cron.txt

Lines changed: 0 additions & 3 deletions
This file was deleted.

docker-compose.yml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,9 @@ services:
55
context: .
66
dockerfile: Dockerfile
77
ports:
8-
- '3000:3000'
8+
- '127.0.0.1:3000:3000'
9+
env_file:
10+
- .env
911
restart: unless-stopped
1012
extra_hosts:
1113
- "host.docker.internal:host-gateway"
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
-- Prevent duplicate alert_reports rows when concurrent scheduler ticks
2+
-- or manual route invocations race on the same report_number.
3+
-- Apply manually on production after deduping existing rows, e.g.:
4+
--
5+
-- DELETE FROM alert_reports a
6+
-- USING alert_reports b
7+
-- WHERE a.id < b.id
8+
-- AND a.report_number = b.report_number;
9+
--
10+
ALTER TABLE alert_reports
11+
ADD CONSTRAINT alert_reports_report_number_key UNIQUE (report_number);

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
},
1212
"dependencies": {
1313
"axios": "^1.10.0",
14+
"croner": "^10.0.1",
1415
"dotenv": "^17.2.0",
1516
"fast-xml-parser": "^5.2.5",
1617
"fastify": "^5.4.0",

src/config/config.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ export interface Config {
1111
database: DatabaseConfig
1212
telegram_token: string
1313
chat_id: string
14+
alert_zone: string
1415
}
1516

1617
export const getNodeEnv = (): NodeEnv => process.env.NODE_ENV as NodeEnv

src/config/development.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ export const developmentConfig: Config = {
1313
},
1414
telegram_token: process.env.TELEGRAM_2_TOKEN as string,
1515
chat_id: process.env.CHAT_ID as string,
16+
alert_zone: process.env.ALERT_ZONE || 'D1',
1617
}

0 commit comments

Comments
 (0)