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 {config, ensureDirectoriesExist} from "./src/config.ts";
|
||||||
import {refreshThreadsEntirely} from "./src/threads/refresh.ts";
|
import {UnitManager} from "./src/bones/Unit.ts";
|
||||||
|
import {ThreadRefresher} from "./src/units/threads.ts";
|
||||||
|
import {HttpServer} from "./src/units/http-server.ts";
|
||||||
|
|
||||||
;(async () => {
|
;(async () => {
|
||||||
await ensureDirectoriesExist()
|
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 = {
|
const maybeConfig: any = {
|
||||||
mail: {
|
mail: {
|
||||||
|
refreshIntervalInSeconds: process.env.CHROUS_REFRESH_INTERVAL_IN_SECONDS || 60,
|
||||||
imap: {
|
imap: {
|
||||||
host: process.env.CHORUS_IMAP_HOST,
|
host: process.env.CHORUS_IMAP_HOST,
|
||||||
port: process.env.CHORUS_IMAP_PORT || 993,
|
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({
|
const commentsConfigSchema = z.object({
|
||||||
mail: z.object({
|
mail: z.object({
|
||||||
|
refreshIntervalInSeconds: z.number({ coerce: true }),
|
||||||
imap: z.object({
|
imap: z.object({
|
||||||
host: z.string(),
|
host: z.string(),
|
||||||
port: z.number({ coerce: true }),
|
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