@sha1n/fungus
Version:
A dependency based service graph controller library
80 lines (66 loc) • 2.23 kB
text/typescript
import { retryAround, simpleRetryPolicy, TimeUnit } from '@sha1n/about-time';
import http from 'http';
import { RuntimeContext, Service } from '../..';
import { createLogger, Logger } from '../../lib/logger';
import startEchoServer from './echoServer';
type HttpServiceMetadata = {
id: string;
scheme: string;
host: string;
port: number;
url: string;
toString: () => string;
};
class EchoService implements Service {
private logger: Logger;
private stopHttpServer: () => Promise<void>;
constructor(readonly id: string) {
this.logger = createLogger(this.id);
}
async start(ctx: RuntimeContext): Promise<HttpServiceMetadata> {
this.logger.info(`start called with context of env: ${ctx.name}`);
this.logger.info(`available services: ${Array.from(ctx.catalog.values()).join(', ')}`);
this.logger.info(`staring ${this.id}...`);
const { stop, scheme, address, port } = await startEchoServer();
this.stopHttpServer = stop;
const url = `${scheme}://${address}:${port}`;
this.logger.info(`checking whether '${url}' is alive`);
await retryAround(() => this.isAlive(url), simpleRetryPolicy(3, 1, { units: TimeUnit.Seconds }));
return {
id: this.id,
scheme,
host: address,
port: port,
url,
toString: () => {
return `[${this.id} -> ${url}]`;
}
};
}
async stop(ctx: RuntimeContext): Promise<void> {
this.logger.info(`stop called with context of env: ${ctx.name}`);
if (this.stopHttpServer) {
this.logger.info(`stopping ${this.id}...`);
await this.stopHttpServer();
}
}
async isAlive(url: string): Promise<boolean> {
return new Promise((resolve, reject) => {
const request = http.get(url, res => {
if (!res.statusCode && res.statusCode !== 200) {
reject(new Error(`Server returned status ${res.statusCode}`));
}
resolve(true);
});
request.on('error', reject);
request.setTimeout(100, () => {
reject(new Error('Timeout'));
});
});
}
}
function createEchoService(id: string): Service {
return new EchoService(id);
}
export { createEchoService, HttpServiceMetadata };
export default createEchoService;