import { LogContext } from '@rocicorp/logger';
import Fastify, {} from 'fastify';
import { HeartbeatMonitor } from "./life-cycle.js";
import { RunningState } from "./running-state.js";
/**
 * Common functionality for all HttpServices. These include:
 * * Responding to health checks at "/"
 * * Tracking optional heartbeats at "/keepalive" and draining when they stop.
 */
export class HttpService {
    id;
    _lc;
    #fastify;
    #port;
    #state;
    #heartbeatMonitor;
    #init;
    constructor(id, lc, opts, init) {
        this.id = id;
        this._lc = lc.withContext('component', this.id);
        this.#fastify = Fastify();
        this.#port = opts.port;
        this.#init = init;
        this.#state = new RunningState(id);
        this.#heartbeatMonitor = new HeartbeatMonitor(this._lc);
    }
    /** Override to delay responding to health checks on "/". */
    _respondToHealthCheck() {
        return true;
    }
    /** Override to delay responding to health checks on "/keepalive". */
    _respondToKeepalive() {
        return true;
    }
    // start() is used in unit tests.
    // run() is the lifecycle method called by the ServiceRunner.
    async start() {
        this.#fastify.get('/', (_req, res) => res.send('OK'));
        this.#fastify.get('/keepalive', ({ headers }, res) => {
            this.#heartbeatMonitor.onHeartbeat(headers);
            return res.send('OK');
        });
        await this.#init(this.#fastify);
        const address = await this.#fastify.listen({
            host: '::',
            port: this.#port,
        });
        this._lc.info?.(`${this.id} listening at ${address}`);
        return address;
    }
    async run() {
        await this.start();
        await this.#state.stopped();
    }
    async stop() {
        this._lc.info?.(`${this.id}: no longer accepting connections`);
        this.#heartbeatMonitor.stop();
        await this.#fastify.close();
        this.#state.stop(this._lc);
    }
}
//# sourceMappingURL=http-service.js.map