Map caching, clickhouse test service

This commit is contained in:
cracklesparkle
2024-08-26 16:11:37 +09:00
parent 579bbf7764
commit ab88fd5ea5
20 changed files with 737 additions and 220 deletions

177
monitor/.gitignore vendored Normal file
View File

@ -0,0 +1,177 @@
# Based on https://raw.githubusercontent.com/github/gitignore/main/Node.gitignore
# Logs
logs
_.log
npm-debug.log_
yarn-debug.log*
yarn-error.log*
lerna-debug.log*
.pnpm-debug.log*
# Caches
.cache
# Diagnostic reports (https://nodejs.org/api/report.html)
report.[0-9]_.[0-9]_.[0-9]_.[0-9]_.json
# Runtime data
pids
_.pid
_.seed
*.pid.lock
# Directory for instrumented libs generated by jscoverage/JSCover
lib-cov
# Coverage directory used by tools like istanbul
coverage
*.lcov
# nyc test coverage
.nyc_output
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
.grunt
# Bower dependency directory (https://bower.io/)
bower_components
# node-waf configuration
.lock-wscript
# Compiled binary addons (https://nodejs.org/api/addons.html)
build/Release
# Dependency directories
node_modules/
jspm_packages/
# Snowpack dependency directory (https://snowpack.dev/)
web_modules/
# TypeScript cache
*.tsbuildinfo
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Optional stylelint cache
.stylelintcache
# Microbundle cache
.rpt2_cache/
.rts2_cache_cjs/
.rts2_cache_es/
.rts2_cache_umd/
# Optional REPL history
.node_repl_history
# Output of 'npm pack'
*.tgz
# Yarn Integrity file
.yarn-integrity
# dotenv environment variable files
.env
.env.development.local
.env.test.local
.env.production.local
.env.local
# parcel-bundler cache (https://parceljs.org/)
.parcel-cache
# Next.js build output
.next
out
# Nuxt.js build / generate output
.nuxt
dist
# Gatsby files
# Comment in the public line in if your project uses Gatsby and not Next.js
# https://nextjs.org/blog/next-9-1#public-directory-support
# public
# vuepress build output
.vuepress/dist
# vuepress v2.x temp and cache directory
.temp
# Docusaurus cache and generated files
.docusaurus
# Serverless directories
.serverless/
# FuseBox cache
.fusebox/
# DynamoDB Local files
.dynamodb/
# TernJS port file
.tern-port
# Stores VSCode versions used for testing VSCode extensions
.vscode-test
# yarn v2
.yarn/cache
.yarn/unplugged
.yarn/build-state.yml
.yarn/install-state.gz
.pnp.*
# IntelliJ based IDEs
.idea
# Finder (MacOS) folder config
.DS_Store
data

19
monitor/Dockerfile Normal file
View File

@ -0,0 +1,19 @@
# Start with an official lightweight image
FROM oven/bun:slim
# Set the working directory in the container
WORKDIR /app
# Copy the current directory contents into the container at /app
COPY . .
# Install project dependencies
RUN bun install
ENV MONITOR_PORT=$MONITOR_PORT
# Expose the port the app runs on
EXPOSE $MONITOR_PORT
# Command to run the application
CMD ["bun", "index.ts"]

15
monitor/README.md Normal file
View File

@ -0,0 +1,15 @@
# monitor
To install dependencies:
```bash
bun install
```
To run:
```bash
bun run index.ts
```
This project was created using `bun init` in bun v1.1.21. [Bun](https://bun.sh) is a fast all-in-one JavaScript runtime.

BIN
monitor/bun.lockb Normal file

Binary file not shown.

97
monitor/index.ts Normal file
View File

@ -0,0 +1,97 @@
import { serve } from 'bun';
import { Database } from 'bun:sqlite';
const db = new Database('./data/servers.db');
// Initialize the database table if it doesn't exist
db.run(`
CREATE TABLE IF NOT EXISTS servers (
id INTEGER PRIMARY KEY AUTOINCREMENT,
name TEXT NOT NULL,
ip TEXT NOT NULL,
ping_rate INTEGER NOT NULL
)
`);
// Function to check server availability
async function checkServer(server: { name: string; ip: string; ping_rate: number; }) {
try {
const response = await Bun.spawn(['ping', '-c', '1', server.ip]);
if (response.exitCode === 0) {
console.log(`[${new Date().toISOString()}] ${server.name} (${server.ip}) is up.`);
} else {
console.error(`[${new Date().toISOString()}] ${server.name} (${server.ip}) is down!`);
}
} catch (error) {
console.error(`[${new Date().toISOString()}] Error pinging ${server.name} (${server.ip}):`, error);
}
}
// Function to monitor servers based on their individual ping rates
async function monitorServer(server: any) {
while (true) {
await checkServer(server);
await new Promise(resolve => setTimeout(resolve, server.ping_rate));
}
}
// Start monitoring all servers
async function startMonitoring() {
const servers = db.query(`SELECT * FROM servers`).all();
servers.forEach(server => monitorServer(server));
}
// Start monitoring in the background
startMonitoring();
// API Server to manage servers
const server = serve({
port: process.env.MONITOR_PORT || 1234,
fetch: async (req) => {
const url = new URL(req.url);
const pathname = url.pathname;
const method = req.method;
if (pathname === '/servers' && method === 'GET') {
const servers = db.query(`SELECT * FROM servers`).all();
return new Response(JSON.stringify(servers), {
headers: { 'Content-Type': 'application/json' },
});
}
if (pathname === '/server' && method === 'POST') {
const data = await req.json();
const { name, ip, ping_rate } = data;
if (!name || !ip || !ping_rate) {
return new Response('Missing fields', { status: 400 });
}
db.run(
`INSERT INTO servers (name, ip, ping_rate) VALUES (?, ?, ?)`,
name, ip, ping_rate
);
return new Response('Server added', { status: 201 });
}
if (pathname.startsWith('/server/') && method === 'PUT') {
const id = pathname.split('/').pop();
const data = await req.json();
const { name, ip, ping_rate } = data;
if (!id || !name || !ip || !ping_rate) {
return new Response('Missing fields', { status: 400 });
}
db.run(
`UPDATE servers SET name = ?, ip = ?, ping_rate = ? WHERE id = ?`,
name, ip, ping_rate, id
);
return new Response('Server updated', { status: 200 });
}
return new Response('Not Found', { status: 404 });
},
});
console.log(`API server and monitoring running on http://localhost:${server.port}`);

11
monitor/package.json Normal file
View File

@ -0,0 +1,11 @@
{
"name": "monitor",
"module": "index.ts",
"type": "module",
"devDependencies": {
"@types/bun": "latest"
},
"peerDependencies": {
"typescript": "^5.0.0"
}
}

27
monitor/tsconfig.json Normal file
View File

@ -0,0 +1,27 @@
{
"compilerOptions": {
// Enable latest features
"lib": ["ESNext", "DOM"],
"target": "ESNext",
"module": "ESNext",
"moduleDetection": "force",
"jsx": "react-jsx",
"allowJs": true,
// Bundler mode
"moduleResolution": "bundler",
"allowImportingTsExtensions": true,
"verbatimModuleSyntax": true,
"noEmit": true,
// Best practices
"strict": true,
"skipLibCheck": true,
"noFallthroughCasesInSwitch": true,
// Some stricter flags (disabled by default)
"noUnusedLocals": false,
"noUnusedParameters": false,
"noPropertyAccessFromIndexSignature": false
}
}