service-keepalive 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +40 -0
- package/LICENSE +21 -0
- package/README.md +420 -0
- package/dist/bin.js +1129 -0
- package/dist/bin.js.map +1 -0
- package/dist/index.cjs +1142 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.cts +375 -0
- package/dist/index.d.ts +375 -0
- package/dist/index.js +1121 -0
- package/dist/index.js.map +1 -0
- package/package.json +83 -0
package/CHANGELOG.md
ADDED
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to this project will be documented in this file.
|
|
4
|
+
|
|
5
|
+
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
|
6
|
+
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
|
|
7
|
+
|
|
8
|
+
## [1.0.0] - 2026-08-16
|
|
9
|
+
|
|
10
|
+
### Added
|
|
11
|
+
|
|
12
|
+
- **Core Library (`KeepAlive`)**:
|
|
13
|
+
- Programmable keep-alive scheduler with explicit `.start()`, `.stop()`, and `.pingOnce()` lifecycle.
|
|
14
|
+
- Native `fetch` HTTP requests with zero heavy network dependencies.
|
|
15
|
+
- Accurate high-resolution response timing via `performance.now()`.
|
|
16
|
+
- Configurable timeouts using `AbortController`.
|
|
17
|
+
- Configurable HTTP methods, custom headers, and optional request bodies.
|
|
18
|
+
- Status matcher validation (default 2xx range, custom status code lists, or custom predicate functions).
|
|
19
|
+
- **Multi-Service Manager (`MultiKeepAlive`)**:
|
|
20
|
+
- Support for monitoring and pinging multiple endpoints simultaneously with individual or shared schedules.
|
|
21
|
+
- **Intelligent Retries**:
|
|
22
|
+
- Exponential, linear, and fixed backoff strategies with ±20% randomized jitter.
|
|
23
|
+
- Maximum delay boundaries and cancellable sleep timers.
|
|
24
|
+
- **Human-Readable Duration Parsing**:
|
|
25
|
+
- Supports `ms`, `s`, `m`, `h`, `d` (e.g. `10s`, `1m`, `5m`, `10m`, `1h`, `500ms`).
|
|
26
|
+
- Strict validation guarding against zero, negative numbers, and malformed strings.
|
|
27
|
+
- **CLI & NPX Support**:
|
|
28
|
+
- Executable `service-keepalive` binary.
|
|
29
|
+
- Flags for `--url`, `--interval`, `--timeout`, `--method`, `--retries`, `--retry-delay`, `--header`, `--config`, `--once`, `--quiet`, `--verbose`.
|
|
30
|
+
- Signal trapping for clean `SIGINT` (Ctrl+C) and `SIGTERM` shutdown.
|
|
31
|
+
- **Configuration & Environment Variables**:
|
|
32
|
+
- Automatic loading of `keepalive.config.json`, `.keepaliverc`, and `.js`/`.mjs`/`.cjs` config files.
|
|
33
|
+
- Environment variable overrides (`KEEPALIVE_URL`, `KEEPALIVE_INTERVAL`, `KEEPALIVE_TIMEOUT`, etc.).
|
|
34
|
+
- **Security & Secret Masking**:
|
|
35
|
+
- Automatic redaction of sensitive request headers (`Authorization`, `Cookie`, `X-Api-Key`, `Token`, `Secret`) and URL query parameters in logs.
|
|
36
|
+
- **Developer Experience & Tooling**:
|
|
37
|
+
- Dual ESM and CommonJS bundle via `tsup` with `.d.ts` and `.d.cts` declarations.
|
|
38
|
+
- Comprehensive deterministic test suite powered by Vitest and local mock HTTP servers.
|
|
39
|
+
- ESLint 9 flat config + Prettier.
|
|
40
|
+
- Production-ready Dockerfile and GitHub Actions workflows (`ci.yml`, `keepalive.yml`, `publish.yml`).
|
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 service-keepalive contributors
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,420 @@
|
|
|
1
|
+
# service-keepalive
|
|
2
|
+
|
|
3
|
+
> Production-ready, lightweight HTTP keep-alive utility and CLI to prevent idle service spin-down on cloud platforms where inbound traffic maintains active status.
|
|
4
|
+
|
|
5
|
+
[](https://www.npmjs.com/package/service-keepalive)
|
|
6
|
+
[](https://github.com/EZDevanshu/service-keepalive/actions/workflows/ci.yml)
|
|
7
|
+
[](https://opensource.org/licenses/MIT)
|
|
8
|
+
[](https://nodejs.org)
|
|
9
|
+
|
|
10
|
+
---
|
|
11
|
+
|
|
12
|
+
## What is it?
|
|
13
|
+
|
|
14
|
+
Many cloud hosting platforms (such as **Render**, **Fly.io**, **Railway**, or **Koyeb**) offer free or hobby-tier web services that automatically spin down into an idle state after 15–30 minutes of inactivity. When a new user requests the service, it can suffer a cold-start delay of 30–60 seconds while the container wakes up.
|
|
15
|
+
|
|
16
|
+
`service-keepalive` periodically sends lightweight HTTP requests to your deployed web service so that inbound traffic keeps the service warm and responsive.
|
|
17
|
+
|
|
18
|
+
### ⚠️ IMPORTANT: External Execution Model
|
|
19
|
+
|
|
20
|
+
```
|
|
21
|
+
┌─────────────────────────────────────────────────────────┐
|
|
22
|
+
│ EXTERNAL RUNNER (Where service-keepalive MUST run) │
|
|
23
|
+
│ │
|
|
24
|
+
│ • Your Local PC / Mac / Raspberry Pi │
|
|
25
|
+
│ • VPS (DigitalOcean, Hetzner, AWS EC2, Linode, etc.) │
|
|
26
|
+
│ • GitHub Actions Scheduled Workflow (Cron) │
|
|
27
|
+
│ • Docker Container on home server / NAS │
|
|
28
|
+
└────────────────────────────┬────────────────────────────┘
|
|
29
|
+
│
|
|
30
|
+
Periodic HTTP Pings (e.g. every 10m)
|
|
31
|
+
│
|
|
32
|
+
▼
|
|
33
|
+
┌─────────────────────────────────────────────────────────┐
|
|
34
|
+
│ TARGET CLOUD SERVICE (e.g. Render, Railway, Fly.io) │
|
|
35
|
+
│ │
|
|
36
|
+
│ • Web API / Backend Server │
|
|
37
|
+
│ • Woken up & kept active by inbound HTTP traffic │
|
|
38
|
+
└─────────────────────────────────────────────────────────┘
|
|
39
|
+
```
|
|
40
|
+
|
|
41
|
+
> [!IMPORTANT]
|
|
42
|
+
> **This package is NOT hosted inside your target server.**
|
|
43
|
+
>
|
|
44
|
+
> It must run **externally** (on your local machine, a separate VPS, a Docker container, or a scheduled CI runner like GitHub Actions). If your server is asleep, internal background timers cannot wake it up. An **external** inbound request is required.
|
|
45
|
+
|
|
46
|
+
---
|
|
47
|
+
|
|
48
|
+
## Hosting Provider Policy & Terms of Service
|
|
49
|
+
|
|
50
|
+
> [!WARNING]
|
|
51
|
+
>
|
|
52
|
+
> - **Compliance**: Always check your hosting provider’s **Terms of Service (ToS)**, Acceptable Use Policy, and free-tier limits before setting up keep-alive pings.
|
|
53
|
+
> - **Free Tier Quotas**: Free-tier plans often have a monthly quota of active instance hours (e.g., Render provides 750 free instance hours per month shared across all your free web services). Keeping a service active 24/7 consumes 720–744 hours per month, which may deplete your free tier allowance for other services.
|
|
54
|
+
> - **No Guarantees**: This package does **not** bypass provider-level billing or platform restrictions, nor does it guarantee 100% uptime. Platforms can modify their sleep policies at any time.
|
|
55
|
+
|
|
56
|
+
---
|
|
57
|
+
|
|
58
|
+
## Features
|
|
59
|
+
|
|
60
|
+
- ⚡ **Zero Heavy Dependencies**: Uses Node.js native `fetch` and lightweight utilities.
|
|
61
|
+
- 🕒 **Human-Readable Intervals**: Accepts durations like `10s`, `1m`, `5m`, `10m`, `1h`, or numeric milliseconds.
|
|
62
|
+
- 🔄 **Configurable Retries & Backoff**: Exponential, linear, or fixed backoff with jitter to handle intermittent network hiccups gracefully.
|
|
63
|
+
- 🛡️ **Timeout & AbortController**: Every ping is guarded by a configurable timeout so requests never hang indefinitely.
|
|
64
|
+
- 🔒 **Security-First**: Automatically redacts authorization headers, API keys, cookies, and secret tokens in logs.
|
|
65
|
+
- 🚦 **Multiple Services**: Keep one or dozens of endpoints warm with individual or shared schedules.
|
|
66
|
+
- 💻 **CLI & NPX Ready**: Instant execution with zero setup using `npx service-keepalive`.
|
|
67
|
+
- 📦 **Dual ESM & CommonJS**: Full compatibility with modern ESM projects and legacy CommonJS runtimes.
|
|
68
|
+
- 🛑 **Graceful Shutdown**: Intercepts `SIGINT` (Ctrl+C) and `SIGTERM` to safely clean up in-flight requests and timers.
|
|
69
|
+
- 🤖 **GitHub Actions & Docker**: Ready-to-use scheduled workflow and multi-stage container image.
|
|
70
|
+
|
|
71
|
+
---
|
|
72
|
+
|
|
73
|
+
## Installation
|
|
74
|
+
|
|
75
|
+
### Run directly without installation (CLI)
|
|
76
|
+
|
|
77
|
+
```bash
|
|
78
|
+
npx service-keepalive --url https://example.onrender.com/health --interval 10m
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
### Install globally (CLI)
|
|
82
|
+
|
|
83
|
+
```bash
|
|
84
|
+
npm install -g service-keepalive
|
|
85
|
+
service-keepalive --url https://example.onrender.com/health
|
|
86
|
+
```
|
|
87
|
+
|
|
88
|
+
### Install as project dependency (Library API)
|
|
89
|
+
|
|
90
|
+
```bash
|
|
91
|
+
npm install service-keepalive
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## CLI Usage
|
|
97
|
+
|
|
98
|
+
### Basic Command
|
|
99
|
+
|
|
100
|
+
```bash
|
|
101
|
+
service-keepalive --url https://example.onrender.com/health --interval 10m
|
|
102
|
+
```
|
|
103
|
+
|
|
104
|
+
### CLI Flags & Options
|
|
105
|
+
|
|
106
|
+
| Option | Shorthand | Description | Default |
|
|
107
|
+
| :------------------------- | :-------- | :------------------------------------------------- | :---------------------- |
|
|
108
|
+
| `--url <url>` | `-u` | Target endpoint URL to ping | _Required_ |
|
|
109
|
+
| `--interval <duration>` | `-i` | Interval between pings (`10s`, `5m`, `10m`, `1h`) | `10m` |
|
|
110
|
+
| `--timeout <duration>` | `-t` | Request timeout before aborting (`10s`, `30s`) | `30s` |
|
|
111
|
+
| `--method <method>` | `-m` | HTTP method (`GET`, `POST`, `HEAD`, etc.) | `GET` |
|
|
112
|
+
| `--retries <number>` | `-r` | Number of retry attempts on failure | `3` |
|
|
113
|
+
| `--retry-delay <duration>` | | Base delay before retrying failed requests | `5s` |
|
|
114
|
+
| `--header <key:value>` | `-H` | Custom header (can be specified multiple times) | |
|
|
115
|
+
| `--config <path>` | `-c` | Path to JSON or JS configuration file | `keepalive.config.json` |
|
|
116
|
+
| `--once` | | Execute a single ping cycle and exit (for Cron/CI) | `false` |
|
|
117
|
+
| `--quiet` | `-q` | Suppress routine logs; only output errors | `false` |
|
|
118
|
+
| `--verbose` | `-v` | Enable detailed debug logs and response headers | `false` |
|
|
119
|
+
| `--help` | `-h` | Display help screen | |
|
|
120
|
+
| `--version` | `-V` | Output package version | |
|
|
121
|
+
|
|
122
|
+
### CLI Examples
|
|
123
|
+
|
|
124
|
+
```bash
|
|
125
|
+
# Ping every 5 minutes with a 15-second timeout
|
|
126
|
+
npx service-keepalive -u https://api.example.com/health -i 5m -t 15s
|
|
127
|
+
|
|
128
|
+
# Send custom headers (e.g. authentication or custom user-agent)
|
|
129
|
+
npx service-keepalive -u https://api.example.com/health -H "Authorization: Bearer mytoken" -H "X-Client: KeepAlive"
|
|
130
|
+
|
|
131
|
+
# Run a single ping check (exits with code 0 on success, 1 on failure)
|
|
132
|
+
npx service-keepalive -u https://api.example.com/health --once
|
|
133
|
+
|
|
134
|
+
# Run using a configuration file
|
|
135
|
+
npx service-keepalive --config keepalive.config.json
|
|
136
|
+
```
|
|
137
|
+
|
|
138
|
+
---
|
|
139
|
+
|
|
140
|
+
## Library Usage
|
|
141
|
+
|
|
142
|
+
### TypeScript Example
|
|
143
|
+
|
|
144
|
+
```typescript
|
|
145
|
+
import { KeepAlive, PingResult } from 'service-keepalive';
|
|
146
|
+
|
|
147
|
+
const keepAlive = new KeepAlive({
|
|
148
|
+
url: 'https://example.onrender.com/health',
|
|
149
|
+
interval: '10m', // Ping every 10 minutes
|
|
150
|
+
timeout: '30s', // 30s timeout per request
|
|
151
|
+
method: 'GET',
|
|
152
|
+
retries: 3,
|
|
153
|
+
retryDelay: '5s',
|
|
154
|
+
headers: {
|
|
155
|
+
'User-Agent': 'service-keepalive-bot/1.0',
|
|
156
|
+
},
|
|
157
|
+
});
|
|
158
|
+
|
|
159
|
+
// Listen to lifecycle and telemetry events
|
|
160
|
+
keepAlive.on('start', name => console.log(`Started keepalive for ${name}`));
|
|
161
|
+
keepAlive.on('ping', ({ url, attempt }) => console.log(`Pinging ${url} (Attempt ${attempt})`));
|
|
162
|
+
keepAlive.on('success', (result: PingResult) =>
|
|
163
|
+
console.log(`✓ ${result.status} in ${result.durationMs}ms`),
|
|
164
|
+
);
|
|
165
|
+
keepAlive.on('failure', (result: PingResult) => console.error(`✗ Failed: ${result.error}`));
|
|
166
|
+
keepAlive.on('retry', info =>
|
|
167
|
+
console.warn(`↻ Retrying in ${info.delayMs}ms due to: ${info.error}`),
|
|
168
|
+
);
|
|
169
|
+
|
|
170
|
+
// Explicitly start the keep-alive scheduler
|
|
171
|
+
keepAlive.start();
|
|
172
|
+
|
|
173
|
+
// Gracefully stop whenever needed
|
|
174
|
+
// await keepAlive.stop();
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### JavaScript (ESM) Example
|
|
178
|
+
|
|
179
|
+
```javascript
|
|
180
|
+
import { KeepAlive } from 'service-keepalive';
|
|
181
|
+
|
|
182
|
+
const keepAlive = new KeepAlive({
|
|
183
|
+
url: 'https://api.example.com/health',
|
|
184
|
+
interval: '5m',
|
|
185
|
+
});
|
|
186
|
+
|
|
187
|
+
keepAlive.start();
|
|
188
|
+
```
|
|
189
|
+
|
|
190
|
+
### JavaScript (CommonJS) Example
|
|
191
|
+
|
|
192
|
+
```javascript
|
|
193
|
+
const { KeepAlive } = require('service-keepalive');
|
|
194
|
+
|
|
195
|
+
const keepAlive = new KeepAlive({
|
|
196
|
+
url: 'https://api.example.com/health',
|
|
197
|
+
interval: '5m',
|
|
198
|
+
});
|
|
199
|
+
|
|
200
|
+
keepAlive.start();
|
|
201
|
+
```
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Multiple Services
|
|
206
|
+
|
|
207
|
+
Manage and ping multiple endpoints concurrently with unified or per-service schedules using `MultiKeepAlive`:
|
|
208
|
+
|
|
209
|
+
```typescript
|
|
210
|
+
import { MultiKeepAlive } from 'service-keepalive';
|
|
211
|
+
|
|
212
|
+
const multi = new MultiKeepAlive({
|
|
213
|
+
// Global defaults applied to all services
|
|
214
|
+
defaults: {
|
|
215
|
+
timeout: '30s',
|
|
216
|
+
retries: 3,
|
|
217
|
+
retryDelay: '5s',
|
|
218
|
+
},
|
|
219
|
+
services: [
|
|
220
|
+
{
|
|
221
|
+
name: 'backend-api',
|
|
222
|
+
url: 'https://backend.example.onrender.com/health',
|
|
223
|
+
interval: '10m',
|
|
224
|
+
},
|
|
225
|
+
{
|
|
226
|
+
name: 'auth-service',
|
|
227
|
+
url: 'https://auth.example.onrender.com/status',
|
|
228
|
+
interval: '15m',
|
|
229
|
+
},
|
|
230
|
+
{
|
|
231
|
+
name: 'worker-node',
|
|
232
|
+
url: 'https://worker.example.onrender.com/ping',
|
|
233
|
+
interval: '5m',
|
|
234
|
+
},
|
|
235
|
+
],
|
|
236
|
+
});
|
|
237
|
+
|
|
238
|
+
// Starts keep-alive for all services
|
|
239
|
+
multi.start();
|
|
240
|
+
|
|
241
|
+
// Stop all services when shutting down
|
|
242
|
+
process.on('SIGINT', async () => {
|
|
243
|
+
await multi.stop();
|
|
244
|
+
process.exit(0);
|
|
245
|
+
});
|
|
246
|
+
```
|
|
247
|
+
|
|
248
|
+
---
|
|
249
|
+
|
|
250
|
+
## Configuration File
|
|
251
|
+
|
|
252
|
+
You can store your settings in a configuration file (`keepalive.config.json` or `keepalive.config.js`).
|
|
253
|
+
|
|
254
|
+
### Example `keepalive.config.json`
|
|
255
|
+
|
|
256
|
+
```json
|
|
257
|
+
{
|
|
258
|
+
"defaults": {
|
|
259
|
+
"timeout": "30s",
|
|
260
|
+
"retries": 3,
|
|
261
|
+
"retryDelay": "5s",
|
|
262
|
+
"retryStrategy": "exponential"
|
|
263
|
+
},
|
|
264
|
+
"services": [
|
|
265
|
+
{
|
|
266
|
+
"name": "backend-api",
|
|
267
|
+
"url": "https://example.onrender.com/health",
|
|
268
|
+
"interval": "10m"
|
|
269
|
+
},
|
|
270
|
+
{
|
|
271
|
+
"name": "auth-service",
|
|
272
|
+
"url": "https://auth.example.com/status",
|
|
273
|
+
"interval": "15m",
|
|
274
|
+
"headers": {
|
|
275
|
+
"User-Agent": "service-keepalive/custom"
|
|
276
|
+
}
|
|
277
|
+
}
|
|
278
|
+
]
|
|
279
|
+
}
|
|
280
|
+
```
|
|
281
|
+
|
|
282
|
+
Run with:
|
|
283
|
+
|
|
284
|
+
```bash
|
|
285
|
+
npx service-keepalive
|
|
286
|
+
# Or with explicit config path:
|
|
287
|
+
npx service-keepalive --config ./path/to/keepalive.config.json
|
|
288
|
+
```
|
|
289
|
+
|
|
290
|
+
---
|
|
291
|
+
|
|
292
|
+
## Environment Variables
|
|
293
|
+
|
|
294
|
+
All primary settings can be configured via environment variables:
|
|
295
|
+
|
|
296
|
+
| Variable | Description | Example |
|
|
297
|
+
| :---------------------- | :-------------------------------------- | :------------------------------------ |
|
|
298
|
+
| `KEEPALIVE_URL` | Target service URL | `https://example.onrender.com/health` |
|
|
299
|
+
| `KEEPALIVE_INTERVAL` | Ping interval | `10m` |
|
|
300
|
+
| `KEEPALIVE_TIMEOUT` | Request timeout | `30s` |
|
|
301
|
+
| `KEEPALIVE_METHOD` | HTTP method | `GET` |
|
|
302
|
+
| `KEEPALIVE_RETRIES` | Max retries | `3` |
|
|
303
|
+
| `KEEPALIVE_RETRY_DELAY` | Base retry delay | `5s` |
|
|
304
|
+
| `KEEPALIVE_HEADERS` | Headers (JSON or comma-separated pairs) | `{"Authorization":"Bearer ..."}` |
|
|
305
|
+
| `KEEPALIVE_CONFIG` | Path to configuration file | `./keepalive.config.json` |
|
|
306
|
+
| `KEEPALIVE_QUIET` | Suppress routine logs | `true` |
|
|
307
|
+
| `KEEPALIVE_VERBOSE` | Enable debug logs | `true` |
|
|
308
|
+
|
|
309
|
+
---
|
|
310
|
+
|
|
311
|
+
## GitHub Actions
|
|
312
|
+
|
|
313
|
+
You can use GitHub Actions to ping your service periodically for free without hosting a long-running daemon.
|
|
314
|
+
|
|
315
|
+
> [!NOTE]
|
|
316
|
+
> **Schedule Delays / Jitter**: GitHub Actions cron schedules run on a best-effort basis. During high GitHub infrastructure load, scheduled runs may occasionally be delayed by a few minutes.
|
|
317
|
+
|
|
318
|
+
Create `.github/workflows/keepalive.yml`:
|
|
319
|
+
|
|
320
|
+
```yaml
|
|
321
|
+
name: Service Keep-Alive
|
|
322
|
+
|
|
323
|
+
on:
|
|
324
|
+
schedule:
|
|
325
|
+
# Run every 10 minutes
|
|
326
|
+
- cron: '*/10 * * * *'
|
|
327
|
+
workflow_dispatch:
|
|
328
|
+
|
|
329
|
+
jobs:
|
|
330
|
+
keepalive:
|
|
331
|
+
name: Ping Service
|
|
332
|
+
runs-on: ubuntu-latest
|
|
333
|
+
steps:
|
|
334
|
+
- name: Setup Node.js
|
|
335
|
+
uses: actions/setup-node@v4
|
|
336
|
+
with:
|
|
337
|
+
node-version: '20'
|
|
338
|
+
|
|
339
|
+
- name: Execute Ping
|
|
340
|
+
env:
|
|
341
|
+
TARGET_URL: ${{ secrets.KEEPALIVE_URL }}
|
|
342
|
+
run: |
|
|
343
|
+
npx service-keepalive "$TARGET_URL" --timeout 30s --retries 3 --once
|
|
344
|
+
```
|
|
345
|
+
|
|
346
|
+
---
|
|
347
|
+
|
|
348
|
+
## Docker Support
|
|
349
|
+
|
|
350
|
+
A lightweight Dockerfile is included for running `service-keepalive` as a background container on your VPS, server, or Raspberry Pi.
|
|
351
|
+
|
|
352
|
+
### Build the image
|
|
353
|
+
|
|
354
|
+
```bash
|
|
355
|
+
docker build -t service-keepalive .
|
|
356
|
+
```
|
|
357
|
+
|
|
358
|
+
### Run the container
|
|
359
|
+
|
|
360
|
+
```bash
|
|
361
|
+
docker run -d \
|
|
362
|
+
--name keepalive \
|
|
363
|
+
--restart unless-stopped \
|
|
364
|
+
-e KEEPALIVE_URL="https://example.onrender.com/health" \
|
|
365
|
+
-e KEEPALIVE_INTERVAL="10m" \
|
|
366
|
+
service-keepalive
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
---
|
|
370
|
+
|
|
371
|
+
## Configuration Reference
|
|
372
|
+
|
|
373
|
+
| Property | Type | Default | Description |
|
|
374
|
+
| :-------------------- | :------------------------------------- | :-------------- | :--------------------------------------------------------- |
|
|
375
|
+
| `url` | `string` | _Required_ | Target URL to ping (http or https) |
|
|
376
|
+
| `name` | `string` | URL hostname | Friendly identifier for logs and events |
|
|
377
|
+
| `interval` | `string \| number` | `'10m'` | Interval between consecutive pings (`10s`, `5m`, `1h`, ms) |
|
|
378
|
+
| `timeout` | `string \| number` | `'30s'` | Request timeout duration before aborting |
|
|
379
|
+
| `method` | `string` | `'GET'` | HTTP request method (`GET`, `POST`, `HEAD`, etc.) |
|
|
380
|
+
| `headers` | `Record<string, string>` | `{}` | Custom request headers |
|
|
381
|
+
| `body` | `string \| null` | `null` | Optional request body for POST/PUT requests |
|
|
382
|
+
| `retries` | `number` | `3` | Max retry attempts upon failure |
|
|
383
|
+
| `retryDelay` | `string \| number` | `'5s'` | Initial base delay before retrying |
|
|
384
|
+
| `retryStrategy` | `'exponential' \| 'linear' \| 'fixed'` | `'exponential'` | Delay calculation algorithm |
|
|
385
|
+
| `retryJitter` | `boolean` | `true` | Applies ±20% randomization to prevent request collisions |
|
|
386
|
+
| `maxRetryDelay` | `string \| number` | `'60s'` | Maximum upper boundary for retry delays |
|
|
387
|
+
| `expectedStatusCodes` | `number[] \| Function` | `200..299` | Status codes considered successful |
|
|
388
|
+
| `logLevel` | `'quiet' \| 'normal' \| 'verbose'` | `'normal'` | Terminal logging verbosity |
|
|
389
|
+
| `logger` | `LoggerInterface \| false` | Built-in | Custom logger instance or `false` to disable |
|
|
390
|
+
| `unrefTimer` | `boolean` | `false` | Whether timers allow Node event loop to exit |
|
|
391
|
+
|
|
392
|
+
---
|
|
393
|
+
|
|
394
|
+
## Troubleshooting
|
|
395
|
+
|
|
396
|
+
### 1. "Request timed out after 30000ms"
|
|
397
|
+
|
|
398
|
+
- **Cause**: The service was spun down and cold-starting, taking longer than the configured timeout to boot and respond.
|
|
399
|
+
- **Solution**: Increase the timeout setting to `60s` or `90s` (e.g. `--timeout 60s`).
|
|
400
|
+
|
|
401
|
+
### 2. "Request failed - HTTP 404 / 500"
|
|
402
|
+
|
|
403
|
+
- **Cause**: The target health check URL path does not exist on your service or your server threw an unhandled error.
|
|
404
|
+
- **Solution**: Verify the endpoint URL in your browser or curl (e.g. ensure `/health` or `/` returns a 200 OK status).
|
|
405
|
+
|
|
406
|
+
### 3. "My service still spun down despite keep-alive pings"
|
|
407
|
+
|
|
408
|
+
- **Cause 1**: The interval might be too long (e.g., your provider spins down after 15 minutes, but your interval was 20m). Set interval to `10m` or `5m`.
|
|
409
|
+
- **Cause 2**: You might have exhausted your monthly free-tier instance hours.
|
|
410
|
+
- **Cause 3**: Ensure `service-keepalive` is running **externally**, not deployed within the sleeping instance itself.
|
|
411
|
+
|
|
412
|
+
---
|
|
413
|
+
|
|
414
|
+
## Contributing
|
|
415
|
+
|
|
416
|
+
Contributions are welcome! Please read [CONTRIBUTING.md](CONTRIBUTING.md) for development setup and testing guidelines.
|
|
417
|
+
|
|
418
|
+
## License
|
|
419
|
+
|
|
420
|
+
This project is licensed under the [MIT License](LICENSE).
|