Clean up index.ts and implement basic http server
This commit is contained in:
parent
36e21fcf7d
commit
a0e9061352
16
index.ts
16
index.ts
@ -1,7 +1,17 @@
|
||||
import {ensureDirectoriesExist} from "./src/config.ts";
|
||||
import {refreshThreadsEntirely} from "./src/threads/refresh.ts";
|
||||
import {config, ensureDirectoriesExist} from "./src/config.ts";
|
||||
import {UnitManager} from "./src/bones/Unit.ts";
|
||||
import {ThreadRefresher} from "./src/units/threads.ts";
|
||||
import {HttpServer} from "./src/units/http-server.ts";
|
||||
|
||||
;(async () => {
|
||||
await ensureDirectoriesExist()
|
||||
await refreshThreadsEntirely()
|
||||
|
||||
const manager = new UnitManager()
|
||||
|
||||
await manager.addUnit(new ThreadRefresher)
|
||||
if ( config.http.enabled ) {
|
||||
await manager.addUnit(new HttpServer)
|
||||
}
|
||||
|
||||
await manager.run()
|
||||
})()
|
||||
|
65
src/bones/Unit.ts
Normal file
65
src/bones/Unit.ts
Normal file
@ -0,0 +1,65 @@
|
||||
import type {Maybe} from "./types.ts";
|
||||
|
||||
export abstract class Unit {
|
||||
public abstract up(): Promise<void>
|
||||
public abstract down(): Promise<void>
|
||||
}
|
||||
|
||||
export class UnitManager {
|
||||
private state: 'init' | 'starting' | 'running' | 'stopping' | 'stopped' = 'init'
|
||||
private pendingUnits: Unit[] = []
|
||||
private runningUnits: Unit[] = []
|
||||
|
||||
public async addUnit(unit: Unit): Promise<void> {
|
||||
this.pendingUnits.push(unit)
|
||||
}
|
||||
|
||||
public getState(): typeof this.state {
|
||||
return this.state
|
||||
}
|
||||
|
||||
public async run(): Promise<void> {
|
||||
await this.start()
|
||||
console.log('Press Ctrl-C to stop.')
|
||||
await new Promise<void>(res => {
|
||||
process.on('SIGINT', () => res())
|
||||
})
|
||||
await this.stop()
|
||||
}
|
||||
|
||||
public async start(): Promise<void> {
|
||||
this.state = 'starting'
|
||||
|
||||
let unit: Maybe<Unit>
|
||||
while ( unit = this.pendingUnits.shift() ) {
|
||||
try {
|
||||
await unit.up()
|
||||
} catch (e) {
|
||||
console.error('Error when starting unit')
|
||||
console.error(e)
|
||||
await this.stop()
|
||||
throw e
|
||||
}
|
||||
|
||||
this.runningUnits.push(unit)
|
||||
}
|
||||
|
||||
this.state = 'running'
|
||||
}
|
||||
|
||||
public async stop(): Promise<void> {
|
||||
this.state = 'stopping'
|
||||
|
||||
let unit: Maybe<Unit>
|
||||
while ( unit = this.runningUnits.shift() ) {
|
||||
try {
|
||||
await unit.down()
|
||||
} catch (e) {
|
||||
console.error('Error while stopping:')
|
||||
console.error(e)
|
||||
}
|
||||
}
|
||||
|
||||
this.state = 'stopped'
|
||||
}
|
||||
}
|
@ -3,6 +3,7 @@ import {castCommentsConfig, type CommentsConfig} from "./types.ts";
|
||||
|
||||
const maybeConfig: any = {
|
||||
mail: {
|
||||
refreshIntervalInSeconds: process.env.CHROUS_REFRESH_INTERVAL_IN_SECONDS || 60,
|
||||
imap: {
|
||||
host: process.env.CHORUS_IMAP_HOST,
|
||||
port: process.env.CHORUS_IMAP_PORT || 993,
|
||||
|
@ -1,11 +0,0 @@
|
||||
import {config} from "../config.ts";
|
||||
|
||||
export async function runHttpServer() {
|
||||
Bun.serve({
|
||||
hostname: config.http.address,
|
||||
port: config.http.port,
|
||||
fetch: async request => {
|
||||
|
||||
},
|
||||
})
|
||||
}
|
@ -2,6 +2,7 @@ import {z} from "zod";
|
||||
|
||||
const commentsConfigSchema = z.object({
|
||||
mail: z.object({
|
||||
refreshIntervalInSeconds: z.number({ coerce: true }),
|
||||
imap: z.object({
|
||||
host: z.string(),
|
||||
port: z.number({ coerce: true }),
|
||||
|
34
src/units/http-server.ts
Normal file
34
src/units/http-server.ts
Normal file
@ -0,0 +1,34 @@
|
||||
import {Unit} from "../bones/Unit.ts";
|
||||
import type {Maybe} from "../bones";
|
||||
import {config} from "../config.ts";
|
||||
|
||||
export class HttpServer extends Unit {
|
||||
private server: Maybe<ReturnType<typeof Bun.serve>>
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.server = Bun.serve({
|
||||
hostname: config.http.address,
|
||||
port: config.http.port,
|
||||
fetch: async request => {
|
||||
const path = `${config.dirs.data}${new URL(request.url).pathname}`
|
||||
const file = Bun.file(path)
|
||||
return new Response(file)
|
||||
},
|
||||
error: () => new Response(
|
||||
JSON.stringify({ success: false, message: 'Not found.' }),
|
||||
{
|
||||
status: 404,
|
||||
headers: {
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
}
|
||||
)
|
||||
})
|
||||
console.log(`Listening on ${config.http.address}:${config.http.port}`)
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
console.log('Stopping server...')
|
||||
await this.server?.stop?.(true)
|
||||
}
|
||||
}
|
38
src/units/threads.ts
Normal file
38
src/units/threads.ts
Normal file
@ -0,0 +1,38 @@
|
||||
import {Unit} from "../bones/Unit.ts";
|
||||
import type {Maybe} from "../bones";
|
||||
import {undefined} from "zod";
|
||||
import {refreshThreadsEntirely} from "../threads/refresh.ts";
|
||||
import {config} from "../config.ts";
|
||||
|
||||
export class ThreadRefresher extends Unit {
|
||||
private handle: Maybe<Timer>
|
||||
private running: boolean = false
|
||||
|
||||
async up(): Promise<void> {
|
||||
this.handle = setInterval(async () => {
|
||||
if ( this.running ) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.running = true
|
||||
try {
|
||||
console.log('Refreshing threads...')
|
||||
await refreshThreadsEntirely()
|
||||
} catch (e) {
|
||||
this.running = false
|
||||
throw e
|
||||
}
|
||||
|
||||
console.log('Done.')
|
||||
this.running = false
|
||||
}, config.mail.refreshIntervalInSeconds * 1000)
|
||||
}
|
||||
|
||||
async down(): Promise<void> {
|
||||
if ( this.handle ) {
|
||||
console.log('Stopping refresh interval...')
|
||||
clearInterval(this.handle)
|
||||
console.log('Done.')
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user