fix(acme-http-client): Destroy keep-alive HTTP agents and DNS client on shutdown to allow process exit; add destroy() on AcmeHttpClient and AcmeClient, wire agents into requests, and call client/smartdns destroy during SmartAcme.stop; documentation clarifications and expanded README (error handling, examples, default retry values).

This commit is contained in:
2026-02-15 20:43:06 +00:00
parent e968f8a039
commit 52e1295fd2
6 changed files with 114 additions and 38 deletions

View File

@@ -3,6 +3,6 @@
*/
export const commitinfo = {
name: '@push.rocks/smartacme',
version: '9.0.0',
version: '9.0.1',
description: 'A TypeScript-based ACME client for LetsEncrypt certificate management with a focus on simplicity and power.'
}

View File

@@ -96,4 +96,11 @@ export class AcmeClient {
async getCertificate(order: IAcmeOrder): Promise<string> {
return this.orderManager.getCertificate(order);
}
/**
* Destroy HTTP transport to release sockets and allow process exit.
*/
destroy(): void {
this.httpClient.destroy();
}
}

View File

@@ -17,11 +17,23 @@ export class AcmeHttpClient {
private nonce: string | null = null;
public kid: string | null = null;
private logger?: TAcmeLogger;
private httpsAgent: https.Agent;
private httpAgent: http.Agent;
constructor(directoryUrl: string, accountKeyPem: string, logger?: TAcmeLogger) {
this.directoryUrl = directoryUrl;
this.accountKeyPem = accountKeyPem;
this.logger = logger;
this.httpsAgent = new https.Agent({ keepAlive: false });
this.httpAgent = new http.Agent({ keepAlive: false });
}
/**
* Destroy HTTP agents to release sockets and allow process exit.
*/
destroy(): void {
this.httpsAgent.destroy();
this.httpAgent.destroy();
}
private log(level: string, message: string, data?: any): void {
@@ -186,6 +198,7 @@ export class AcmeHttpClient {
path: urlObj.pathname + urlObj.search,
method,
headers: requestHeaders,
agent: isHttps ? this.httpsAgent : this.httpAgent,
};
const req = lib.request(options, (res) => {

View File

@@ -169,6 +169,14 @@ export class SmartAcme {
process.removeListener('SIGTERM', this.boundSigtermHandler);
this.boundSigtermHandler = null;
}
// Destroy ACME HTTP transport (closes keep-alive sockets)
if (this.client) {
this.client.destroy();
}
// Destroy DNS client (kills Rust bridge child process if spawned)
if (this.smartdns) {
this.smartdns.destroy();
}
if (this.certmanager && typeof (this.certmanager as any).close === 'function') {
await (this.certmanager as any).close();
}