Skip to content

Commit 4479831

Browse files
committed
feat(binlog)
1 parent deca8eb commit 4479831

File tree

12 files changed

+1231
-173
lines changed

12 files changed

+1231
-173
lines changed

.vscode/settings.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
{
22
"cSpell.words": [
33
"andrewl",
4+
"binlog",
45
"Customizer",
56
"ejson",
67
"Randomizer",

docs/index.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,10 @@ features:
5050
icon: 🪄
5151
details: Renderer for terminal output with flexible layouts and CLI components.
5252
link: /reference/@andrew_l/vue-stdout/
53+
- title: Binlog
54+
icon: 📝
55+
details: A high-performance binary logging system for Node.js applications.
56+
link: /reference/@andrew_l/binlog/
5357
---
5458

5559
## Getting Started

packages/binlog/README.md

Lines changed: 172 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,172 @@
1+
# Binlog
2+
3+
![license](https://img.shields.io/npm/l/%40andrew_l%2Fbinlog) <!-- omit in toc -->
4+
![npm version](https://img.shields.io/npm/v/%40andrew_l%2Fbinlog) <!-- omit in toc -->
5+
![npm bundle size](https://img.shields.io/bundlephobia/minzip/%40andrew_l%2Fbinlog) <!-- omit in toc -->
6+
7+
A high-performance binary logging system for Node.js applications, inspired by VK's KPHP KDB binlog implementation. This library provides a robust, efficient way to record and replay binary log entries with integrity checking and rotation support.
8+
9+
## 📋 Features
10+
11+
- **Automatic log rotation** based on file size
12+
- **TL serialization** integration for complex data types
13+
- **Data integrity** verification via CRC32 checksums
14+
- **File system sync control** for durability vs performance tradeoffs
15+
16+
<!-- install placeholder -->
17+
18+
## 🔧 Usage
19+
20+
### Basic Example
21+
22+
```typescript
23+
import { createBinlog } from '@andrew_l/binlog';
24+
25+
async function main() {
26+
// Create a binlog with default options
27+
const binlog = createBinlog({
28+
path: './logs/app-{index}.bin',
29+
});
30+
31+
// Initialize binlog system
32+
await binlog.init();
33+
34+
// Open the binlog for writing
35+
await binlog.open();
36+
37+
// Write entries with various opcodes and data
38+
await binlog.write(1, { message: 'Application started' });
39+
await binlog.write(2, { user: 'john', action: 'login' });
40+
41+
// Close the binlog when done
42+
await binlog.close();
43+
}
44+
45+
main().catch(console.error);
46+
```
47+
48+
### Reading Binlog Entries
49+
50+
```typescript
51+
import { createBinlog } from '@andrew_l/binlog';
52+
53+
async function readLogs() {
54+
const binlog = createBinlog({
55+
path: './logs/app-{index}.bin',
56+
});
57+
58+
await binlog.init();
59+
60+
// Read entries from a specific binlog file
61+
const entries = await binlog.readEntries<{
62+
message?: string;
63+
user?: string;
64+
action?: string;
65+
}>('app-0.bin');
66+
67+
// Process entries
68+
for (const entry of entries) {
69+
console.log(
70+
`[${new Date(entry.timestamp * 1000).toISOString()}] Op: ${entry.opcode}`,
71+
);
72+
console.log(entry.data);
73+
}
74+
}
75+
76+
readLogs().catch(console.error);
77+
```
78+
79+
### Configuration Options
80+
81+
```typescript
82+
import { createBinlog } from '@andrew_l/binlog';
83+
84+
const binlog = createBinlog({
85+
// File path pattern with {index} placeholder for rotation
86+
path: './logs/application-{index}.bin',
87+
88+
// Maximum file size before rotation (100MB)
89+
maxFileSize: 104857600,
90+
91+
// Enable/disable log rotation
92+
rotation: true,
93+
94+
// Control synchronous writes for durability
95+
syncWrites: true,
96+
});
97+
```
98+
99+
## ⚙️ API Reference
100+
101+
#### Methods
102+
103+
- **`async init(): Promise<void>`**
104+
Initialize the binlog system, ensuring directory exists and pick most recent binlog file.
105+
106+
- **`async open(): Promise<void>`**
107+
Open the binlog for writing.
108+
109+
- **`async close(): Promise<void>`**
110+
Close the current binlog file.
111+
112+
- **`async write(opcode: number, data: unknown): Promise<void>`**
113+
Write a binlog entry with the specified opcode and data.
114+
115+
- **`async rotate(): Promise<void>`**
116+
Rotate the binlog file to a new one.
117+
118+
- **`async readEntries<TData = Buffer>(filename: string, unsafe?: boolean): Promise<BinlogEntry<TData>[]>`**
119+
Read and parse all entries from a binlog file.
120+
121+
#### Properties
122+
123+
- **`currentFileIndex: number`**
124+
Get the current binlog file index.
125+
126+
- **`currentFileName: string`**
127+
Get current binlog file name.
128+
129+
- **`directory: string`**
130+
Get current binlog directory.
131+
132+
## 🛡️ Binlog File Format
133+
134+
Each binlog file has:
135+
136+
- **File Header** (16 bytes)
137+
138+
- Magic number (4 bytes): 0x4442544B
139+
- Version (4 bytes): Currently 1
140+
- Timestamp (4 bytes)
141+
- Reserved (4 bytes)
142+
143+
- **Entry Headers** (20 bytes each)
144+
145+
- Operation code (4 bytes)
146+
- Flags (4 bytes)
147+
- Timestamp (4 bytes)
148+
- Data length (4 bytes)
149+
- CRC32 checksum (4 bytes)
150+
151+
- **Entry Data** (variable length)
152+
- Raw binary data or TL-encoded data
153+
154+
## 🔄 Integration with TL-Pack
155+
156+
Binlog automatically uses TL serialization for non-Buffer data types using the `@andrew_l/tl-pack` library. This allows for efficient serialization of complex JavaScript objects.
157+
158+
```typescript
159+
// Data will be automatically TL-encoded
160+
await binlog.write(1, {
161+
user: 'alice',
162+
permissions: ['read', 'write'],
163+
metadata: {
164+
lastLogin: new Date(),
165+
requestCount: 42,
166+
},
167+
});
168+
```
169+
170+
## 📝 License
171+
172+
MIT

packages/binlog/build.config.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
import { defineBuildConfig } from 'unbuild';
2+
3+
export default defineBuildConfig({
4+
entries: ['src/index.ts'],
5+
declaration: true,
6+
sourcemap: true,
7+
rollup: {
8+
emitCJS: true,
9+
},
10+
});

packages/binlog/package.json

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
{
2+
"name": "@andrew_l/binlog",
3+
"version": "0.2.14",
4+
"license": "MIT",
5+
"type": "module",
6+
"keywords": [
7+
"binlog"
8+
],
9+
"repository": {
10+
"type": "git",
11+
"url": "git+https://github.com/men232/toolkit.git",
12+
"directory": "packages/binlog"
13+
},
14+
"scripts": {
15+
"build": "unbuild",
16+
"prepack": "unbuild",
17+
"test": "vitest run --typecheck",
18+
"test:watch": "vitest watch --typecheck"
19+
},
20+
"exports": {
21+
".": {
22+
"import": "./dist/index.mjs",
23+
"require": "./dist/index.cjs"
24+
}
25+
},
26+
"main": "./dist/index.cjs",
27+
"types": "./dist/index.d.ts",
28+
"files": [
29+
"dist"
30+
],
31+
"devDependencies": {
32+
"@types/node": "catalog:",
33+
"typescript": "catalog:",
34+
"unbuild": "catalog:",
35+
"vitest": "catalog:"
36+
},
37+
"dependencies": {
38+
"@andrew_l/tl-pack": "workspace:*",
39+
"@andrew_l/toolkit": "workspace:*"
40+
}
41+
}

0 commit comments

Comments
 (0)