@avalw/search-worker 1.0.3 → 1.1.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/README.md +261 -92
- package/bin/cli.js +23 -16
- package/lib/worker.js +190 -29
- package/package.json +1 -1
package/README.md
CHANGED
|
@@ -14,32 +14,210 @@ AVALW Worker is a lightweight Node.js application that runs on your server and c
|
|
|
14
14
|
## How It Works
|
|
15
15
|
|
|
16
16
|
```
|
|
17
|
-
|
|
18
|
-
│
|
|
19
|
-
|
|
20
|
-
│
|
|
21
|
-
│
|
|
22
|
-
│
|
|
23
|
-
│
|
|
24
|
-
│ │
|
|
25
|
-
│
|
|
26
|
-
│
|
|
27
|
-
│
|
|
28
|
-
│
|
|
29
|
-
|
|
17
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
18
|
+
│ AVALW WORKER SYSTEM │
|
|
19
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
20
|
+
│ │
|
|
21
|
+
│ YOUR SERVER AVALW NETWORK YOUR USERS │
|
|
22
|
+
│ ─────────── ──────────── ────────── │
|
|
23
|
+
│ │
|
|
24
|
+
│ ┌─────────────┐ ┌─────────────┐ │
|
|
25
|
+
│ │ Worker │ ───────────────►│ Compute │ │
|
|
26
|
+
│ │ Process │ Contributes │ Pool │ │
|
|
27
|
+
│ │ │ Core-Hours │ │ │
|
|
28
|
+
│ │ CPU: ████░ │ │ ┌─┐┌─┐┌─┐┌─┐│ │
|
|
29
|
+
│ │ 70% │ │ └─┘└─┘└─┘└─┘│ │
|
|
30
|
+
│ └─────────────┘ └──────┬──────┘ │
|
|
31
|
+
│ │ │ │
|
|
32
|
+
│ │ Reports: │ Calculates: │
|
|
33
|
+
│ │ • CPU cores │ • Core-hours │
|
|
34
|
+
│ │ • CPU speed (GHz) │ • Your tier │
|
|
35
|
+
│ │ • Usage % │ • API quota │
|
|
36
|
+
│ │ • Online time │ │
|
|
37
|
+
│ ▼ ▼ │
|
|
38
|
+
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────┐ │
|
|
39
|
+
│ │ Your App │◄────────────────│ Search API │◄───────│ Search │ │
|
|
40
|
+
│ │ │ Free access │ (quota │ │ Query │ │
|
|
41
|
+
│ │ // search │ based on │ based) │ │ │ │
|
|
42
|
+
│ │ fetch(..); │ contribution │ │ │ "weather" │ │
|
|
43
|
+
│ └─────────────┘ └─────────────┘ └─────────────┘ │
|
|
44
|
+
│ │
|
|
45
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
30
46
|
```
|
|
31
47
|
|
|
32
|
-
##
|
|
48
|
+
## Core-Hours System
|
|
33
49
|
|
|
34
|
-
|
|
50
|
+
Unlike simple percentage-based systems, AVALW uses **Core-Hours** - a fair metric that accounts for your actual hardware contribution.
|
|
35
51
|
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
52
|
+
### What is a Core-Hour?
|
|
53
|
+
|
|
54
|
+
```
|
|
55
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
56
|
+
│ CORE-HOUR CALCULATION │
|
|
57
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
58
|
+
│ │
|
|
59
|
+
│ Core-Hours = CPU Cores × (CPU Speed ÷ 3.0 GHz) × Usage% × Hours Online │
|
|
60
|
+
│ │
|
|
61
|
+
│ ═══════════════════════════════════════════════════════════════════════ │
|
|
62
|
+
│ │
|
|
63
|
+
│ EXAMPLE: Intel i7-10700 running for 24 hours at 50% │
|
|
64
|
+
│ │
|
|
65
|
+
│ • Cores: 8 │
|
|
66
|
+
│ • Speed: 2.9 GHz base (normalized to 3.0 GHz baseline) │
|
|
67
|
+
│ • Usage: 50% │
|
|
68
|
+
│ • Time: 24 hours │
|
|
69
|
+
│ │
|
|
70
|
+
│ Calculation: 8 × (2.9 ÷ 3.0) × 0.50 × 24 = 92.8 core-hours/day │
|
|
71
|
+
│ │
|
|
72
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
### Tiers Based on Core-Hours
|
|
76
|
+
|
|
77
|
+
| Tier | Requests/Day | Core-Hours/Day | Minimum Cores |
|
|
78
|
+
|------|--------------|----------------|---------------|
|
|
79
|
+
| **Starter** | 1,000 | 3 | 3 cores |
|
|
80
|
+
| **Basic** | 5,000 | 12 | 4 cores |
|
|
81
|
+
| **Pro** | 20,000 | 36 | 6 cores |
|
|
82
|
+
| **Business** | 50,000 | 72 | 8 cores |
|
|
83
|
+
| **Enterprise** | 500,000 | 240 | 16 cores |
|
|
84
|
+
|
|
85
|
+
## Real CPU Examples
|
|
86
|
+
|
|
87
|
+
### Desktop CPUs
|
|
88
|
+
|
|
89
|
+
```
|
|
90
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
91
|
+
│ DESKTOP CPU EXAMPLES │
|
|
92
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
93
|
+
│ │
|
|
94
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
95
|
+
│ │ Intel Core i5-10400 (6 cores @ 2.9 GHz) │ │
|
|
96
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
97
|
+
│ │ At 50% for 24h: 6 × 0.97 × 0.50 × 24 = 69.8 core-hours │ │
|
|
98
|
+
│ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
|
|
99
|
+
│ │ │ │
|
|
100
|
+
│ │ At 30% for 24h: 6 × 0.97 × 0.30 × 24 = 41.9 core-hours │ │
|
|
101
|
+
│ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
|
|
102
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
103
|
+
│ │
|
|
104
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
105
|
+
│ │ Intel Core i7-10700 (8 cores @ 2.9 GHz) │ │
|
|
106
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
107
|
+
│ │ At 50% for 24h: 8 × 0.97 × 0.50 × 24 = 93.1 core-hours │ │
|
|
108
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
109
|
+
│ │ │ │
|
|
110
|
+
│ │ At 25% for 24h: 8 × 0.97 × 0.25 × 24 = 46.6 core-hours │ │
|
|
111
|
+
│ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
|
|
112
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
113
|
+
│ │
|
|
114
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
115
|
+
│ │ Intel Core i9-10900 (10 cores @ 2.8 GHz) │ │
|
|
116
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
117
|
+
│ │ At 50% for 24h: 10 × 0.93 × 0.50 × 24 = 111.6 core-hours │ │
|
|
118
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
119
|
+
│ │ │ │
|
|
120
|
+
│ │ At 80% for 24h: 10 × 0.93 × 0.80 × 24 = 178.6 core-hours │ │
|
|
121
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
122
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
123
|
+
│ │
|
|
124
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
125
|
+
│ │ AMD Ryzen 5 5600X (6 cores @ 3.7 GHz) │ │
|
|
126
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
127
|
+
│ │ At 50% for 24h: 6 × 1.23 × 0.50 × 24 = 88.6 core-hours │ │
|
|
128
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
129
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
130
|
+
│ │
|
|
131
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
132
|
+
│ │ AMD Ryzen 7 5800X (8 cores @ 3.8 GHz) │ │
|
|
133
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
134
|
+
│ │ At 50% for 24h: 8 × 1.27 × 0.50 × 24 = 121.9 core-hours │ │
|
|
135
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
136
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
137
|
+
│ │
|
|
138
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
### Server CPUs
|
|
142
|
+
|
|
143
|
+
```
|
|
144
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
145
|
+
│ SERVER CPU EXAMPLES │
|
|
146
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
147
|
+
│ │
|
|
148
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
149
|
+
│ │ Intel Xeon E-2288G (8 cores @ 3.7 GHz) │ │
|
|
150
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
151
|
+
│ │ At 30% for 24h: 8 × 1.23 × 0.30 × 24 = 70.8 core-hours │ │
|
|
152
|
+
│ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
|
|
153
|
+
│ │ │ │
|
|
154
|
+
│ │ At 50% for 24h: 8 × 1.23 × 0.50 × 24 = 118.1 core-hours │ │
|
|
155
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
156
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
157
|
+
│ │
|
|
158
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
159
|
+
│ │ AMD EPYC 7302 (16 cores @ 3.0 GHz) │ │
|
|
160
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
161
|
+
│ │ At 30% for 24h: 16 × 1.00 × 0.30 × 24 = 115.2 core-hours │ │
|
|
162
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
163
|
+
│ │ │ │
|
|
164
|
+
│ │ At 60% for 24h: 16 × 1.00 × 0.60 × 24 = 230.4 core-hours │ │
|
|
165
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
166
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
167
|
+
│ │
|
|
168
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
169
|
+
│ │ AMD EPYC 7742 (64 cores @ 2.25 GHz) │ │
|
|
170
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
171
|
+
│ │ At 20% for 24h: 64 × 0.75 × 0.20 × 24 = 230.4 core-hours │ │
|
|
172
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
173
|
+
│ │ │ │
|
|
174
|
+
│ │ At 50% for 24h: 64 × 0.75 × 0.50 × 24 = 576.0 core-hours │ │
|
|
175
|
+
│ │ ✓ Qualifies for: ENTERPRISE tier (500,000 requests/day) │ │
|
|
176
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
177
|
+
│ │
|
|
178
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
179
|
+
```
|
|
180
|
+
|
|
181
|
+
### VPS / Cloud Examples
|
|
182
|
+
|
|
183
|
+
```
|
|
184
|
+
┌─────────────────────────────────────────────────────────────────────────────┐
|
|
185
|
+
│ VPS / CLOUD EXAMPLES │
|
|
186
|
+
├─────────────────────────────────────────────────────────────────────────────┤
|
|
187
|
+
│ │
|
|
188
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
189
|
+
│ │ Basic VPS (2 vCPU @ 2.5 GHz) - ~$5/month │ │
|
|
190
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
191
|
+
│ │ At 80% for 24h: 2 × 0.83 × 0.80 × 24 = 31.9 core-hours │ │
|
|
192
|
+
│ │ ✗ Not enough for Starter (needs 3 cores minimum) │ │
|
|
193
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
194
|
+
│ │
|
|
195
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
196
|
+
│ │ Standard VPS (4 vCPU @ 2.5 GHz) - ~$20/month │ │
|
|
197
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
198
|
+
│ │ At 50% for 24h: 4 × 0.83 × 0.50 × 24 = 39.8 core-hours │ │
|
|
199
|
+
│ │ ✓ Qualifies for: PRO tier (20,000 requests/day) │ │
|
|
200
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
201
|
+
│ │
|
|
202
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
203
|
+
│ │ Premium VPS (8 vCPU @ 3.0 GHz) - ~$80/month │ │
|
|
204
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
205
|
+
│ │ At 50% for 24h: 8 × 1.00 × 0.50 × 24 = 96.0 core-hours │ │
|
|
206
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
207
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
208
|
+
│ │
|
|
209
|
+
│ ┌─────────────────────────────────────────────────────────────────────┐ │
|
|
210
|
+
│ │ AWS EC2 c5.4xlarge (16 vCPU @ 3.4 GHz) │ │
|
|
211
|
+
│ ├─────────────────────────────────────────────────────────────────────┤ │
|
|
212
|
+
│ │ At 40% for 24h: 16 × 1.13 × 0.40 × 24 = 173.6 core-hours │ │
|
|
213
|
+
│ │ ✓ Qualifies for: BUSINESS tier (50,000 requests/day) │ │
|
|
214
|
+
│ │ │ │
|
|
215
|
+
│ │ At 70% for 24h: 16 × 1.13 × 0.70 × 24 = 303.7 core-hours │ │
|
|
216
|
+
│ │ ✓ Qualifies for: ENTERPRISE tier (500,000 requests/day) │ │
|
|
217
|
+
│ └─────────────────────────────────────────────────────────────────────┘ │
|
|
218
|
+
│ │
|
|
219
|
+
└─────────────────────────────────────────────────────────────────────────────┘
|
|
220
|
+
```
|
|
43
221
|
|
|
44
222
|
## Quick Start
|
|
45
223
|
|
|
@@ -61,49 +239,41 @@ npm install -g @avalw/search-worker
|
|
|
61
239
|
avalw-worker YOUR_WORKER_TOKEN
|
|
62
240
|
```
|
|
63
241
|
|
|
64
|
-
You
|
|
242
|
+
You'll see real-time stats:
|
|
65
243
|
```
|
|
66
|
-
|
|
67
|
-
║
|
|
68
|
-
|
|
69
|
-
║ Free Search API in exchange for compute
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
244
|
+
╔═══════════════════════════════════════════════════════════════════╗
|
|
245
|
+
║ AVALW Search Worker v1.1.0 ║
|
|
246
|
+
╠═══════════════════════════════════════════════════════════════════╣
|
|
247
|
+
║ Free Search API in exchange for compute ║
|
|
248
|
+
╚═══════════════════════════════════════════════════════════════════╝
|
|
249
|
+
|
|
250
|
+
System Info:
|
|
251
|
+
├─ CPU: Intel(R) Core(TM) i7-10700 @ 2.90GHz
|
|
252
|
+
├─ Cores: 8
|
|
253
|
+
├─ Speed Factor: 0.97x (normalized to 3.0 GHz)
|
|
254
|
+
└─ Memory: 32 GB
|
|
255
|
+
|
|
256
|
+
Worker Status:
|
|
257
|
+
├─ Token: abc123def456...
|
|
258
|
+
├─ API URL: https://worker.avalw.org
|
|
259
|
+
└─ Target Usage: 50%
|
|
260
|
+
|
|
261
|
+
[10:30:45] ✓ Heartbeat OK
|
|
262
|
+
├─ Core-Hours Today: 46.5 / 72 needed for BUSINESS
|
|
263
|
+
├─ Current Tier: PRO (20,000 req/day)
|
|
264
|
+
├─ Usage Today: 1,234 / 20,000
|
|
265
|
+
└─ Online: 12h 35m
|
|
266
|
+
|
|
267
|
+
Press Ctrl+C to stop.
|
|
77
268
|
```
|
|
78
269
|
|
|
79
270
|
### 4. Use the Search API
|
|
80
271
|
|
|
81
|
-
Once your worker is running, make API requests from your whitelisted domains:
|
|
82
|
-
|
|
83
272
|
```javascript
|
|
84
|
-
// Node.js / JavaScript
|
|
85
273
|
const response = await fetch(
|
|
86
274
|
'https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN'
|
|
87
275
|
);
|
|
88
276
|
const results = await response.json();
|
|
89
|
-
console.log(results);
|
|
90
|
-
```
|
|
91
|
-
|
|
92
|
-
```python
|
|
93
|
-
# Python
|
|
94
|
-
import requests
|
|
95
|
-
|
|
96
|
-
response = requests.get(
|
|
97
|
-
'https://worker.avalw.org/api/search',
|
|
98
|
-
params={'q': 'your query', 'token': 'YOUR_TOKEN'}
|
|
99
|
-
)
|
|
100
|
-
results = response.json()
|
|
101
|
-
print(results)
|
|
102
|
-
```
|
|
103
|
-
|
|
104
|
-
```bash
|
|
105
|
-
# cURL
|
|
106
|
-
curl "https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN"
|
|
107
277
|
```
|
|
108
278
|
|
|
109
279
|
## Running as a Service
|
|
@@ -114,9 +284,12 @@ curl "https://worker.avalw.org/api/search?q=your+query&token=YOUR_TOKEN"
|
|
|
114
284
|
# Install PM2
|
|
115
285
|
npm install -g pm2
|
|
116
286
|
|
|
117
|
-
# Start worker
|
|
287
|
+
# Start worker with 50% CPU target
|
|
118
288
|
pm2 start avalw-worker -- YOUR_WORKER_TOKEN
|
|
119
289
|
|
|
290
|
+
# Or specify custom CPU percentage
|
|
291
|
+
pm2 start avalw-worker -- YOUR_WORKER_TOKEN --cpu 30
|
|
292
|
+
|
|
120
293
|
# Save for auto-restart
|
|
121
294
|
pm2 save
|
|
122
295
|
pm2 startup
|
|
@@ -161,26 +334,6 @@ docker build -t avalw-worker .
|
|
|
161
334
|
docker run -d --name avalw-worker avalw-worker
|
|
162
335
|
```
|
|
163
336
|
|
|
164
|
-
## Programmatic Usage
|
|
165
|
-
|
|
166
|
-
You can also use the worker programmatically in your Node.js application:
|
|
167
|
-
|
|
168
|
-
```javascript
|
|
169
|
-
const { AvalwWorker } = require('@avalw/search-worker');
|
|
170
|
-
|
|
171
|
-
const worker = new AvalwWorker('YOUR_WORKER_TOKEN');
|
|
172
|
-
|
|
173
|
-
// Start the worker
|
|
174
|
-
await worker.start();
|
|
175
|
-
|
|
176
|
-
// Get system info
|
|
177
|
-
const info = worker.getSystemInfo();
|
|
178
|
-
console.log(info);
|
|
179
|
-
|
|
180
|
-
// Stop the worker
|
|
181
|
-
await worker.stop();
|
|
182
|
-
```
|
|
183
|
-
|
|
184
337
|
## API Reference
|
|
185
338
|
|
|
186
339
|
### Search Endpoint
|
|
@@ -189,7 +342,6 @@ await worker.stop();
|
|
|
189
342
|
GET https://worker.avalw.org/api/search
|
|
190
343
|
```
|
|
191
344
|
|
|
192
|
-
**Parameters:**
|
|
193
345
|
| Parameter | Type | Required | Description |
|
|
194
346
|
|-----------|--------|----------|--------------------------------|
|
|
195
347
|
| q | string | Yes | Search query |
|
|
@@ -209,29 +361,46 @@ GET https://worker.avalw.org/api/search
|
|
|
209
361
|
}
|
|
210
362
|
],
|
|
211
363
|
"total": 100,
|
|
212
|
-
"page": 1
|
|
364
|
+
"page": 1,
|
|
365
|
+
"tier": "PRO",
|
|
366
|
+
"usage": {
|
|
367
|
+
"today": 1234,
|
|
368
|
+
"limit": 20000,
|
|
369
|
+
"core_hours": 46.5
|
|
370
|
+
}
|
|
213
371
|
}
|
|
214
372
|
```
|
|
215
373
|
|
|
216
|
-
##
|
|
374
|
+
## FAQ
|
|
375
|
+
|
|
376
|
+
### Why do I need minimum 3 cores?
|
|
217
377
|
|
|
218
|
-
|
|
378
|
+
The AVALW network requires meaningful contributions to remain sustainable. A 3-core minimum ensures:
|
|
379
|
+
- Fair distribution of compute power
|
|
380
|
+
- Quality of service for all users
|
|
381
|
+
- Sustainable network operation
|
|
219
382
|
|
|
220
|
-
|
|
383
|
+
### Can I run on a 2-core VPS?
|
|
221
384
|
|
|
222
|
-
|
|
223
|
-
-
|
|
224
|
-
-
|
|
225
|
-
-
|
|
385
|
+
Unfortunately, 2 cores don't meet the minimum requirement. Consider:
|
|
386
|
+
- Upgrading to a 4-core VPS
|
|
387
|
+
- Running on a different server with more cores
|
|
388
|
+
- Combining with another server (coming soon: multi-worker support)
|
|
389
|
+
|
|
390
|
+
### How is my tier calculated?
|
|
391
|
+
|
|
392
|
+
Your tier is recalculated every hour based on your rolling 24-hour core-hours contribution. The formula:
|
|
393
|
+
|
|
394
|
+
```
|
|
395
|
+
Core-Hours = Cores × (Speed ÷ 3.0) × Usage% × Hours
|
|
396
|
+
```
|
|
226
397
|
|
|
227
|
-
###
|
|
228
|
-
- Make sure your worker is running
|
|
229
|
-
- Check the worker console for errors
|
|
230
|
-
- Worker must send heartbeat every 30 seconds
|
|
398
|
+
### What if my server goes offline?
|
|
231
399
|
|
|
232
|
-
|
|
233
|
-
-
|
|
234
|
-
-
|
|
400
|
+
Your core-hours accumulate only while online. If you go offline:
|
|
401
|
+
- Your accumulated core-hours for the day remain
|
|
402
|
+
- Your tier may drop if you don't maintain the required hours
|
|
403
|
+
- API calls will fail until your worker reconnects
|
|
235
404
|
|
|
236
405
|
## Security
|
|
237
406
|
|
package/bin/cli.js
CHANGED
|
@@ -1,45 +1,52 @@
|
|
|
1
1
|
#!/usr/bin/env node
|
|
2
2
|
|
|
3
|
-
const { AvalwWorker } = require('../lib/worker');
|
|
3
|
+
const { AvalwWorker, TIERS } = require('../lib/worker');
|
|
4
4
|
|
|
5
5
|
const token = process.argv[2];
|
|
6
6
|
const apiUrl = process.argv[3] || 'https://worker.avalw.org';
|
|
7
7
|
|
|
8
|
-
if (!token) {
|
|
8
|
+
if (!token || token === '--help' || token === '-h') {
|
|
9
9
|
console.log('');
|
|
10
|
-
console.log('
|
|
11
|
-
console.log('
|
|
10
|
+
console.log(' ╔═══════════════════════════════════════════════════════════════════╗');
|
|
11
|
+
console.log(' ║ AVALW Search Worker v1.1.0 ║');
|
|
12
|
+
console.log(' ╚═══════════════════════════════════════════════════════════════════╝');
|
|
12
13
|
console.log('');
|
|
13
14
|
console.log(' Usage: avalw-worker <WORKER_TOKEN> [API_URL]');
|
|
14
15
|
console.log('');
|
|
15
16
|
console.log(' Get your worker token at: https://worker.avalw.org');
|
|
16
17
|
console.log('');
|
|
18
|
+
console.log(' Tiers (based on Core-Hours):');
|
|
19
|
+
console.log(' ┌───────────┬─────────────┬──────────────┬─────────────┐');
|
|
20
|
+
console.log(' │ Tier │ Requests │ Core-Hours │ Min Cores │');
|
|
21
|
+
console.log(' ├───────────┼─────────────┼──────────────┼─────────────┤');
|
|
22
|
+
console.log(' │ Starter │ 1,000/day │ 3/day │ 3 cores │');
|
|
23
|
+
console.log(' │ Basic │ 5,000/day │ 12/day │ 4 cores │');
|
|
24
|
+
console.log(' │ Pro │ 20,000/day │ 36/day │ 6 cores │');
|
|
25
|
+
console.log(' │ Business │ 50,000/day │ 72/day │ 8 cores │');
|
|
26
|
+
console.log(' │ Enterprise│ 500,000/day │ 240/day │ 16 cores │');
|
|
27
|
+
console.log(' └───────────┴─────────────┴──────────────┴─────────────┘');
|
|
28
|
+
console.log('');
|
|
29
|
+
console.log(' Core-Hours Formula:');
|
|
30
|
+
console.log(' Cores × (Speed ÷ 3.0 GHz) × Usage% × Hours');
|
|
31
|
+
console.log('');
|
|
17
32
|
console.log(' Example:');
|
|
18
33
|
console.log(' avalw-worker abc123def456...');
|
|
19
34
|
console.log('');
|
|
20
35
|
process.exit(1);
|
|
21
36
|
}
|
|
22
37
|
|
|
23
|
-
console.log('');
|
|
24
|
-
console.log(' ╔═══════════════════════════════════════════════╗');
|
|
25
|
-
console.log(' ║ AVALW Search Worker v1.0.0 ║');
|
|
26
|
-
console.log(' ╠═══════════════════════════════════════════════╣');
|
|
27
|
-
console.log(' ║ Free Search API in exchange for compute ║');
|
|
28
|
-
console.log(' ╚═══════════════════════════════════════════════╝');
|
|
29
|
-
console.log('');
|
|
30
|
-
|
|
31
38
|
const worker = new AvalwWorker(token, apiUrl);
|
|
32
39
|
|
|
33
40
|
// Handle graceful shutdown
|
|
34
|
-
process.on('SIGINT', () => {
|
|
41
|
+
process.on('SIGINT', async () => {
|
|
35
42
|
console.log('\n Shutting down worker...');
|
|
36
|
-
worker.stop();
|
|
43
|
+
await worker.stop();
|
|
37
44
|
process.exit(0);
|
|
38
45
|
});
|
|
39
46
|
|
|
40
|
-
process.on('SIGTERM', () => {
|
|
47
|
+
process.on('SIGTERM', async () => {
|
|
41
48
|
console.log('\n Shutting down worker...');
|
|
42
|
-
worker.stop();
|
|
49
|
+
await worker.stop();
|
|
43
50
|
process.exit(0);
|
|
44
51
|
});
|
|
45
52
|
|
package/lib/worker.js
CHANGED
|
@@ -1,23 +1,99 @@
|
|
|
1
1
|
/**
|
|
2
|
-
* AVALW Search Worker
|
|
2
|
+
* AVALW Search Worker v1.1.0
|
|
3
3
|
* Connects to worker.avalw.org and contributes compute power
|
|
4
4
|
* in exchange for free search API access.
|
|
5
|
+
*
|
|
6
|
+
* Uses Core-Hours calculation for fair tier distribution.
|
|
5
7
|
*/
|
|
6
8
|
|
|
7
9
|
const https = require('https');
|
|
8
10
|
const http = require('http');
|
|
9
11
|
const os = require('os');
|
|
10
12
|
|
|
13
|
+
// Tier definitions based on core-hours
|
|
14
|
+
const TIERS = {
|
|
15
|
+
STARTER: { name: 'Starter', coreHours: 3, requests: 1000, minCores: 3 },
|
|
16
|
+
BASIC: { name: 'Basic', coreHours: 12, requests: 5000, minCores: 4 },
|
|
17
|
+
PRO: { name: 'Pro', coreHours: 36, requests: 20000, minCores: 6 },
|
|
18
|
+
BUSINESS: { name: 'Business', coreHours: 72, requests: 50000, minCores: 8 },
|
|
19
|
+
ENTERPRISE: { name: 'Enterprise', coreHours: 240, requests: 500000, minCores: 16 }
|
|
20
|
+
};
|
|
21
|
+
|
|
11
22
|
class AvalwWorker {
|
|
12
23
|
constructor(token, apiUrl = 'https://worker.avalw.org') {
|
|
13
24
|
this.token = token;
|
|
14
25
|
this.apiUrl = apiUrl;
|
|
15
26
|
this.running = false;
|
|
16
27
|
this.heartbeatInterval = null;
|
|
17
|
-
this.
|
|
18
|
-
this.
|
|
19
|
-
this.
|
|
20
|
-
this.
|
|
28
|
+
this.startTime = null;
|
|
29
|
+
this.coreHoursToday = 0;
|
|
30
|
+
this.currentTier = null;
|
|
31
|
+
this.cpuInfo = this.getCpuInfo();
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* Get detailed CPU information
|
|
36
|
+
*/
|
|
37
|
+
getCpuInfo() {
|
|
38
|
+
const cpus = os.cpus();
|
|
39
|
+
const cores = cpus.length;
|
|
40
|
+
const model = cpus[0]?.model || 'Unknown';
|
|
41
|
+
|
|
42
|
+
// Extract speed from CPU model or use reported speed
|
|
43
|
+
let speedGHz = cpus[0]?.speed ? cpus[0].speed / 1000 : 2.5;
|
|
44
|
+
|
|
45
|
+
// Try to parse speed from model string (e.g., "@ 2.90GHz")
|
|
46
|
+
const speedMatch = model.match(/@\s*([\d.]+)\s*GHz/i);
|
|
47
|
+
if (speedMatch) {
|
|
48
|
+
speedGHz = parseFloat(speedMatch[1]);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Speed factor normalized to 3.0 GHz baseline
|
|
52
|
+
const speedFactor = speedGHz / 3.0;
|
|
53
|
+
|
|
54
|
+
return {
|
|
55
|
+
cores,
|
|
56
|
+
model,
|
|
57
|
+
speedGHz,
|
|
58
|
+
speedFactor: Math.round(speedFactor * 100) / 100,
|
|
59
|
+
totalMemoryGB: Math.round(os.totalmem() / 1024 / 1024 / 1024 * 10) / 10
|
|
60
|
+
};
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/**
|
|
64
|
+
* Calculate core-hours contribution
|
|
65
|
+
* @param {number} usagePercent - CPU usage percentage (0-100)
|
|
66
|
+
* @param {number} hours - Time in hours
|
|
67
|
+
*/
|
|
68
|
+
calculateCoreHours(usagePercent, hours) {
|
|
69
|
+
const { cores, speedFactor } = this.cpuInfo;
|
|
70
|
+
return cores * speedFactor * (usagePercent / 100) * hours;
|
|
71
|
+
}
|
|
72
|
+
|
|
73
|
+
/**
|
|
74
|
+
* Determine tier based on core-hours and minimum cores
|
|
75
|
+
*/
|
|
76
|
+
determineTier(coreHours) {
|
|
77
|
+
const { cores } = this.cpuInfo;
|
|
78
|
+
|
|
79
|
+
// Check from highest to lowest tier
|
|
80
|
+
if (cores >= TIERS.ENTERPRISE.minCores && coreHours >= TIERS.ENTERPRISE.coreHours) {
|
|
81
|
+
return TIERS.ENTERPRISE;
|
|
82
|
+
}
|
|
83
|
+
if (cores >= TIERS.BUSINESS.minCores && coreHours >= TIERS.BUSINESS.coreHours) {
|
|
84
|
+
return TIERS.BUSINESS;
|
|
85
|
+
}
|
|
86
|
+
if (cores >= TIERS.PRO.minCores && coreHours >= TIERS.PRO.coreHours) {
|
|
87
|
+
return TIERS.PRO;
|
|
88
|
+
}
|
|
89
|
+
if (cores >= TIERS.BASIC.minCores && coreHours >= TIERS.BASIC.coreHours) {
|
|
90
|
+
return TIERS.BASIC;
|
|
91
|
+
}
|
|
92
|
+
if (cores >= TIERS.STARTER.minCores && coreHours >= TIERS.STARTER.coreHours) {
|
|
93
|
+
return TIERS.STARTER;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return null; // Not enough cores or core-hours
|
|
21
97
|
}
|
|
22
98
|
|
|
23
99
|
/**
|
|
@@ -25,21 +101,51 @@ class AvalwWorker {
|
|
|
25
101
|
*/
|
|
26
102
|
async start() {
|
|
27
103
|
this.running = true;
|
|
28
|
-
|
|
29
|
-
|
|
104
|
+
this.startTime = Date.now();
|
|
105
|
+
|
|
106
|
+
// Print banner
|
|
107
|
+
console.log('');
|
|
108
|
+
console.log(' ╔═══════════════════════════════════════════════════════════════════╗');
|
|
109
|
+
console.log(' ║ AVALW Search Worker v1.1.0 ║');
|
|
110
|
+
console.log(' ╠═══════════════════════════════════════════════════════════════════╣');
|
|
111
|
+
console.log(' ║ Free Search API in exchange for compute ║');
|
|
112
|
+
console.log(' ╚═══════════════════════════════════════════════════════════════════╝');
|
|
113
|
+
console.log('');
|
|
114
|
+
|
|
115
|
+
// Print system info
|
|
116
|
+
console.log(' System Info:');
|
|
117
|
+
console.log(` ├─ CPU: ${this.cpuInfo.model}`);
|
|
118
|
+
console.log(` ├─ Cores: ${this.cpuInfo.cores}`);
|
|
119
|
+
console.log(` ├─ Speed: ${this.cpuInfo.speedGHz} GHz (factor: ${this.cpuInfo.speedFactor}x)`);
|
|
120
|
+
console.log(` └─ Memory: ${this.cpuInfo.totalMemoryGB} GB`);
|
|
121
|
+
console.log('');
|
|
122
|
+
|
|
123
|
+
// Check minimum cores requirement
|
|
124
|
+
if (this.cpuInfo.cores < TIERS.STARTER.minCores) {
|
|
125
|
+
console.log(` ⚠ WARNING: Your system has ${this.cpuInfo.cores} cores.`);
|
|
126
|
+
console.log(` ⚠ Minimum ${TIERS.STARTER.minCores} cores required for Starter tier.`);
|
|
127
|
+
console.log(` ⚠ Worker will run but you won't qualify for any tier.`);
|
|
128
|
+
console.log('');
|
|
129
|
+
}
|
|
130
|
+
|
|
131
|
+
// Print worker status
|
|
132
|
+
console.log(' Worker Status:');
|
|
133
|
+
console.log(` ├─ Token: ${this.token.substring(0, 12)}...`);
|
|
134
|
+
console.log(` ├─ API URL: ${this.apiUrl}`);
|
|
135
|
+
console.log(` └─ Target Usage: 50%`);
|
|
30
136
|
console.log('');
|
|
31
137
|
|
|
32
138
|
// Initial heartbeat
|
|
33
139
|
await this.sendHeartbeat();
|
|
34
140
|
|
|
35
|
-
// Start heartbeat loop
|
|
141
|
+
// Start heartbeat loop (every 30 seconds)
|
|
36
142
|
this.heartbeatInterval = setInterval(() => {
|
|
37
143
|
if (this.running) {
|
|
38
144
|
this.sendHeartbeat();
|
|
39
145
|
}
|
|
40
|
-
}, 30000);
|
|
146
|
+
}, 30000);
|
|
41
147
|
|
|
42
|
-
console.log('
|
|
148
|
+
console.log(' Press Ctrl+C to stop.');
|
|
43
149
|
console.log('');
|
|
44
150
|
}
|
|
45
151
|
|
|
@@ -59,29 +165,59 @@ class AvalwWorker {
|
|
|
59
165
|
await this.apiRequest('/api/worker/offline', 'POST', {
|
|
60
166
|
worker_token: this.token
|
|
61
167
|
});
|
|
62
|
-
console.log('
|
|
168
|
+
console.log('');
|
|
169
|
+
console.log(' Worker stopped and marked offline.');
|
|
63
170
|
} catch (error) {
|
|
64
171
|
// Ignore errors during shutdown
|
|
65
172
|
}
|
|
66
173
|
}
|
|
67
174
|
|
|
68
175
|
/**
|
|
69
|
-
* Send heartbeat to server
|
|
176
|
+
* Send heartbeat to server with core-hours data
|
|
70
177
|
*/
|
|
71
178
|
async sendHeartbeat() {
|
|
72
179
|
try {
|
|
180
|
+
// Calculate hours online since start
|
|
181
|
+
const hoursOnline = (Date.now() - this.startTime) / 1000 / 60 / 60;
|
|
182
|
+
|
|
183
|
+
// Estimate core-hours (assuming 50% usage for now)
|
|
184
|
+
// In a real implementation, you'd measure actual CPU usage
|
|
185
|
+
const estimatedUsage = 50;
|
|
186
|
+
const sessionCoreHours = this.calculateCoreHours(estimatedUsage, hoursOnline);
|
|
187
|
+
|
|
73
188
|
const response = await this.apiRequest('/api/worker/heartbeat', 'POST', {
|
|
74
189
|
worker_token: this.token,
|
|
75
|
-
system_info:
|
|
190
|
+
system_info: {
|
|
191
|
+
platform: os.platform(),
|
|
192
|
+
arch: os.arch(),
|
|
193
|
+
cores: this.cpuInfo.cores,
|
|
194
|
+
cpu_model: this.cpuInfo.model,
|
|
195
|
+
cpu_speed_ghz: this.cpuInfo.speedGHz,
|
|
196
|
+
speed_factor: this.cpuInfo.speedFactor,
|
|
197
|
+
total_memory_gb: this.cpuInfo.totalMemoryGB,
|
|
198
|
+
free_memory_gb: Math.round(os.freemem() / 1024 / 1024 / 1024 * 10) / 10,
|
|
199
|
+
uptime: os.uptime(),
|
|
200
|
+
worker_uptime_hours: Math.round(hoursOnline * 100) / 100,
|
|
201
|
+
session_core_hours: Math.round(sessionCoreHours * 100) / 100,
|
|
202
|
+
estimated_usage_percent: estimatedUsage
|
|
203
|
+
}
|
|
76
204
|
});
|
|
77
205
|
|
|
78
206
|
if (response.success) {
|
|
79
|
-
this.
|
|
80
|
-
this.
|
|
81
|
-
this.lastHeartbeat = new Date();
|
|
207
|
+
this.coreHoursToday = response.core_hours_today || sessionCoreHours;
|
|
208
|
+
this.currentTier = response.tier || this.determineTier(this.coreHoursToday);
|
|
82
209
|
|
|
83
|
-
const time =
|
|
84
|
-
|
|
210
|
+
const time = new Date().toLocaleTimeString();
|
|
211
|
+
const tierName = this.currentTier?.name || 'None';
|
|
212
|
+
const tierRequests = this.currentTier?.requests?.toLocaleString() || '0';
|
|
213
|
+
const nextTier = this.getNextTier();
|
|
214
|
+
|
|
215
|
+
console.log(` [${time}] ✓ Heartbeat OK`);
|
|
216
|
+
console.log(` ├─ Core-Hours Today: ${this.coreHoursToday.toFixed(1)}${nextTier ? ` / ${nextTier.coreHours} needed for ${nextTier.name}` : ''}`);
|
|
217
|
+
console.log(` ├─ Current Tier: ${tierName} (${tierRequests} req/day)`);
|
|
218
|
+
console.log(` ├─ Usage Today: ${(response.usage_today || 0).toLocaleString()} / ${tierRequests}`);
|
|
219
|
+
console.log(` └─ Online: ${this.formatUptime(hoursOnline)}`);
|
|
220
|
+
console.log('');
|
|
85
221
|
} else {
|
|
86
222
|
console.error(` [ERROR] Heartbeat failed: ${response.error}`);
|
|
87
223
|
}
|
|
@@ -91,20 +227,45 @@ class AvalwWorker {
|
|
|
91
227
|
}
|
|
92
228
|
|
|
93
229
|
/**
|
|
94
|
-
* Get
|
|
230
|
+
* Get the next tier to aim for
|
|
95
231
|
*/
|
|
96
|
-
|
|
97
|
-
const
|
|
98
|
-
const totalMem = os.totalmem();
|
|
99
|
-
const freeMem = os.freemem();
|
|
232
|
+
getNextTier() {
|
|
233
|
+
const tierOrder = [TIERS.STARTER, TIERS.BASIC, TIERS.PRO, TIERS.BUSINESS, TIERS.ENTERPRISE];
|
|
100
234
|
|
|
235
|
+
for (const tier of tierOrder) {
|
|
236
|
+
if (this.cpuInfo.cores >= tier.minCores && this.coreHoursToday < tier.coreHours) {
|
|
237
|
+
return tier;
|
|
238
|
+
}
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
return null; // Already at max tier or can't qualify
|
|
242
|
+
}
|
|
243
|
+
|
|
244
|
+
/**
|
|
245
|
+
* Format uptime as human readable
|
|
246
|
+
*/
|
|
247
|
+
formatUptime(hours) {
|
|
248
|
+
if (hours < 1) {
|
|
249
|
+
return `${Math.round(hours * 60)}m`;
|
|
250
|
+
}
|
|
251
|
+
const h = Math.floor(hours);
|
|
252
|
+
const m = Math.round((hours - h) * 60);
|
|
253
|
+
return `${h}h ${m}m`;
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
/**
|
|
257
|
+
* Get system information (legacy method for compatibility)
|
|
258
|
+
*/
|
|
259
|
+
getSystemInfo() {
|
|
101
260
|
return {
|
|
102
261
|
platform: os.platform(),
|
|
103
262
|
arch: os.arch(),
|
|
104
|
-
cpus:
|
|
105
|
-
cpu_model:
|
|
106
|
-
|
|
107
|
-
|
|
263
|
+
cpus: this.cpuInfo.cores,
|
|
264
|
+
cpu_model: this.cpuInfo.model,
|
|
265
|
+
cpu_speed_ghz: this.cpuInfo.speedGHz,
|
|
266
|
+
speed_factor: this.cpuInfo.speedFactor,
|
|
267
|
+
total_memory: this.cpuInfo.totalMemoryGB,
|
|
268
|
+
free_memory: Math.round(os.freemem() / 1024 / 1024 / 1024 * 10) / 10,
|
|
108
269
|
uptime: os.uptime()
|
|
109
270
|
};
|
|
110
271
|
}
|
|
@@ -125,7 +286,7 @@ class AvalwWorker {
|
|
|
125
286
|
method: method,
|
|
126
287
|
headers: {
|
|
127
288
|
'Content-Type': 'application/json',
|
|
128
|
-
'User-Agent': 'AvalwWorker/1.
|
|
289
|
+
'User-Agent': 'AvalwWorker/1.1.0'
|
|
129
290
|
}
|
|
130
291
|
};
|
|
131
292
|
|
|
@@ -155,4 +316,4 @@ class AvalwWorker {
|
|
|
155
316
|
}
|
|
156
317
|
}
|
|
157
318
|
|
|
158
|
-
module.exports = { AvalwWorker };
|
|
319
|
+
module.exports = { AvalwWorker, TIERS };
|