feat(daemon): Add central TSPM daemon and IPC client; refactor CLI to use daemon and improve monitoring/error handling
This commit is contained in:
209
readme.plan.md
Normal file
209
readme.plan.md
Normal file
@@ -0,0 +1,209 @@
|
||||
# TSPM Refactoring Plan: Central Daemon Architecture
|
||||
|
||||
## Problem Analysis
|
||||
|
||||
Currently, each `startAsDaemon` creates an isolated tspm instance with no coordination:
|
||||
|
||||
- Multiple daemons reading/writing same config file
|
||||
- No communication between instances
|
||||
- Inconsistent process management
|
||||
- `tspm list` shows all processes but each daemon only manages its own
|
||||
|
||||
## Proposed Architecture
|
||||
|
||||
### 1. Central Daemon Manager (`ts/classes.daemon.ts`)
|
||||
|
||||
- Single daemon instance managing ALL processes
|
||||
- Runs continuously in background
|
||||
- Uses Unix socket for IPC at `~/.tspm/tspm.sock`
|
||||
- Maintains single source of truth for process state
|
||||
|
||||
### 2. IPC Communication Layer (`ts/classes.ipc.ts`)
|
||||
|
||||
- **Framework**: Use `@push.rocks/smartipc` v2.0.1
|
||||
- **Server**: SmartIpc server in daemon using Unix Domain Socket
|
||||
- **Client**: SmartIpc client in CLI for all operations
|
||||
- **Socket Path**: `~/.tspm/tspm.sock` (Unix) or named pipe (Windows)
|
||||
- **Protocol**: Type-safe request/response with SmartIpc's built-in patterns
|
||||
- **Features**:
|
||||
- Automatic reconnection with exponential backoff
|
||||
- Heartbeat monitoring for daemon health
|
||||
- Type-safe message contracts
|
||||
- **Auto-start**: CLI starts daemon if connection fails
|
||||
|
||||
### 3. New CLI Commands
|
||||
|
||||
- `tspm enable` - Start central daemon using systemd/launchd
|
||||
- `tspm disable` - Stop and disable central daemon
|
||||
- `tspm status` - Show daemon status
|
||||
- Remove `startAsDaemon` (replaced by daemon + `tspm start`)
|
||||
|
||||
### 4. Refactored CLI (`ts/cli.ts`)
|
||||
|
||||
All commands become daemon clients:
|
||||
|
||||
```typescript
|
||||
// Before: Direct process management
|
||||
await tspm.start(config);
|
||||
|
||||
// After: Send to daemon
|
||||
await ipcClient.request('start', config);
|
||||
```
|
||||
|
||||
### 5. File Structure Changes
|
||||
|
||||
```
|
||||
ts/
|
||||
├── classes.daemon.ts # New: Central daemon server
|
||||
├── classes.ipc.ts # New: IPC client/server
|
||||
├── classes.tspm.ts # Modified: Used by daemon only
|
||||
├── cli.ts # Modified: Becomes thin client
|
||||
└── classes.daemonmanager.ts # New: Systemd/launchd integration
|
||||
```
|
||||
|
||||
## Implementation Steps
|
||||
|
||||
### Phase 1: Core Infrastructure
|
||||
|
||||
- [ ] Add `@push.rocks/smartipc` dependency (v2.0.1)
|
||||
- [ ] Create IPC message type definitions for all operations
|
||||
- [ ] Implement daemon server with SmartIpc server
|
||||
- [ ] Create IPC client wrapper for CLI
|
||||
- [ ] Add daemon lifecycle management (enable/disable)
|
||||
|
||||
### Phase 2: CLI Refactoring
|
||||
|
||||
- [ ] Convert all CLI commands to SmartIpc client requests
|
||||
- [ ] Add daemon auto-start logic with connection monitoring
|
||||
- [ ] Leverage SmartIpc's built-in reconnection and error handling
|
||||
- [ ] Implement type-safe message contracts for all commands
|
||||
|
||||
### Phase 3: Migration & Cleanup
|
||||
|
||||
- [ ] Migrate existing config to daemon-compatible format
|
||||
- [ ] Remove `startAsDaemon` command
|
||||
- [ ] Add migration guide for users
|
||||
|
||||
## Technical Details
|
||||
|
||||
### IPC Implementation with SmartIpc
|
||||
|
||||
```typescript
|
||||
// Daemon server setup
|
||||
import { SmartIpc } from '@push.rocks/smartipc';
|
||||
|
||||
const ipcServer = SmartIpc.createServer({
|
||||
id: 'tspm-daemon',
|
||||
socketPath: '~/.tspm/tspm.sock', // Unix socket
|
||||
});
|
||||
|
||||
// Message handlers with type safety
|
||||
ipcServer.onMessage<StartRequest, StartResponse>(
|
||||
'start',
|
||||
async (data, clientId) => {
|
||||
const result = await tspmManager.start(data.config);
|
||||
return { success: true, processId: result.pid };
|
||||
},
|
||||
);
|
||||
|
||||
// CLI client setup
|
||||
const ipcClient = SmartIpc.createClient({
|
||||
id: 'tspm-daemon',
|
||||
socketPath: '~/.tspm/tspm.sock',
|
||||
});
|
||||
|
||||
// Type-safe requests
|
||||
const response = await ipcClient.request<StartRequest, StartResponse>('start', {
|
||||
config: processConfig,
|
||||
});
|
||||
```
|
||||
|
||||
### Message Types
|
||||
|
||||
```typescript
|
||||
interface StartRequest {
|
||||
config: ProcessConfig;
|
||||
}
|
||||
|
||||
interface StartResponse {
|
||||
success: boolean;
|
||||
processId?: number;
|
||||
error?: string;
|
||||
}
|
||||
```
|
||||
|
||||
### Daemon State File
|
||||
|
||||
`~/.tspm/daemon.state` - PID, socket path, version
|
||||
|
||||
### Process Management
|
||||
|
||||
Daemon maintains all ProcessMonitor instances internally, CLI never directly manages processes.
|
||||
|
||||
## Key Benefits
|
||||
|
||||
### Architecture Benefits
|
||||
|
||||
- Single daemon manages all processes
|
||||
- Consistent state management
|
||||
- Efficient resource usage
|
||||
- Better process coordination
|
||||
- Proper service integration with OS
|
||||
|
||||
### SmartIpc Advantages
|
||||
|
||||
- **Cross-platform**: Unix sockets on Linux/macOS, named pipes on Windows
|
||||
- **Type-safe**: Full TypeScript support with generic message types
|
||||
- **Resilient**: Automatic reconnection with exponential backoff
|
||||
- **Observable**: Built-in metrics and heartbeat monitoring
|
||||
- **Performant**: Low-latency messaging with zero external dependencies
|
||||
- **Secure**: Connection limits and message size restrictions
|
||||
|
||||
## Backwards Compatibility
|
||||
|
||||
- Keep existing config format
|
||||
- Auto-migrate on first run
|
||||
- Provide clear upgrade instructions
|
||||
|
||||
## Architecture Diagram
|
||||
|
||||
```
|
||||
┌─────────────┐ IPC ┌──────────────┐
|
||||
│ CLI │◄────────────►│ Daemon │
|
||||
│ (thin client)│ Socket │ (server) │
|
||||
└─────────────┘ └──────────────┘
|
||||
│ │
|
||||
│ ▼
|
||||
│ ┌──────────────┐
|
||||
│ │ Tspm │
|
||||
│ │ Manager │
|
||||
│ └──────────────┘
|
||||
│ │
|
||||
▼ ▼
|
||||
┌─────────────┐ ┌──────────────┐
|
||||
│ User │ │ProcessMonitor│
|
||||
│ Commands │ │ Instances │
|
||||
└─────────────┘ └──────────────┘
|
||||
```
|
||||
|
||||
## Migration Path
|
||||
|
||||
1. **Version 2.0.0-alpha**: Implement daemon with backwards compatibility
|
||||
2. **Version 2.0.0-beta**: Deprecate `startAsDaemon`, encourage daemon mode
|
||||
3. **Version 2.0.0**: Remove legacy code, daemon-only operation
|
||||
4. **Documentation**: Update all examples and guides
|
||||
|
||||
## Security Considerations
|
||||
|
||||
- Unix socket permissions (user-only access)
|
||||
- Validate all IPC messages
|
||||
- Rate limiting for IPC requests
|
||||
- Secure daemon shutdown mechanism
|
||||
|
||||
## Testing Requirements
|
||||
|
||||
- Unit tests for IPC layer
|
||||
- Integration tests for daemon lifecycle
|
||||
- Migration tests from current architecture
|
||||
- Performance tests for multiple processes
|
||||
- Stress tests for IPC communication
|
Reference in New Issue
Block a user