@djangocfg/centrifugo 2.1.72 → 2.1.73
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 +105 -1
- package/package.json +5 -5
- package/src/core/client/CentrifugoRPCClient.ts +10 -0
package/README.md
CHANGED
|
@@ -34,10 +34,13 @@ src/
|
|
|
34
34
|
│ │ ├── CentrifugoRPCClient.ts # Main facade (~165 lines)
|
|
35
35
|
│ │ ├── connection.ts # Connection lifecycle
|
|
36
36
|
│ │ ├── subscriptions.ts # Channel subscriptions
|
|
37
|
-
│ │ ├── rpc.ts # RPC methods (namedRPC, namedRPCNoWait)
|
|
37
|
+
│ │ ├── rpc.ts # RPC methods (namedRPC, namedRPCWithRetry, namedRPCNoWait)
|
|
38
38
|
│ │ ├── version.ts # API version checking
|
|
39
39
|
│ │ ├── types.ts # Type definitions
|
|
40
40
|
│ │ └── index.ts # Exports
|
|
41
|
+
│ ├── errors/ # Error handling with retry logic
|
|
42
|
+
│ │ ├── RPCError.ts # Typed RPC errors (isRetryable, userMessage)
|
|
43
|
+
│ │ └── RPCRetryHandler.ts # Exponential backoff retry
|
|
41
44
|
│ ├── logger/ # Logging system with circular buffer
|
|
42
45
|
│ │ ├── createLogger.ts # Logger factory (supports string prefix)
|
|
43
46
|
│ │ └── LogsStore.ts # In-memory logs accumulation
|
|
@@ -598,6 +601,98 @@ client?.namedRPCNoWait('terminal.input', { session_id, data }, {
|
|
|
598
601
|
| `namedRPC()` | ~800-1800ms | Commands that need response |
|
|
599
602
|
| `namedRPCNoWait()` | ~10-30ms | Real-time input, fire-and-forget |
|
|
600
603
|
|
|
604
|
+
### namedRPCWithRetry() - RPC with Timeout and Retry
|
|
605
|
+
|
|
606
|
+
For operations that need both timeout protection and automatic retry on transient failures.
|
|
607
|
+
|
|
608
|
+
```tsx
|
|
609
|
+
import { useCentrifugo } from '@djangocfg/centrifugo';
|
|
610
|
+
|
|
611
|
+
function FileList() {
|
|
612
|
+
const { client } = useCentrifugo();
|
|
613
|
+
|
|
614
|
+
const loadFiles = async () => {
|
|
615
|
+
// Automatically retries on timeout/network errors
|
|
616
|
+
const files = await client?.namedRPCWithRetry('files.list',
|
|
617
|
+
{ path: '/home' },
|
|
618
|
+
{
|
|
619
|
+
timeout: 5000, // 5 second timeout per attempt
|
|
620
|
+
maxRetries: 3, // Up to 3 retries
|
|
621
|
+
baseDelayMs: 1000, // Start with 1s delay
|
|
622
|
+
maxDelayMs: 10000, // Cap at 10s
|
|
623
|
+
onRetry: (attempt, error, delay) => {
|
|
624
|
+
console.log(`Retry ${attempt}: ${error.userMessage}, waiting ${delay}ms`);
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
);
|
|
628
|
+
return files;
|
|
629
|
+
};
|
|
630
|
+
}
|
|
631
|
+
```
|
|
632
|
+
|
|
633
|
+
### RPCError - Typed Error Handling
|
|
634
|
+
|
|
635
|
+
All RPC methods now throw `RPCError` with classification for better error handling:
|
|
636
|
+
|
|
637
|
+
```tsx
|
|
638
|
+
import { RPCError } from '@djangocfg/centrifugo';
|
|
639
|
+
|
|
640
|
+
try {
|
|
641
|
+
await client.namedRPC('files.list', { path: '/' });
|
|
642
|
+
} catch (error) {
|
|
643
|
+
if (error instanceof RPCError) {
|
|
644
|
+
// Error classification
|
|
645
|
+
console.log(error.code); // 'timeout' | 'network_error' | 'server_error' | ...
|
|
646
|
+
console.log(error.isRetryable); // true for transient errors
|
|
647
|
+
console.log(error.userMessage); // User-friendly message
|
|
648
|
+
console.log(error.suggestedRetryDelay); // Recommended delay in ms
|
|
649
|
+
|
|
650
|
+
// Show user-friendly message
|
|
651
|
+
toast.error(error.userMessage);
|
|
652
|
+
|
|
653
|
+
// Decide if retry makes sense
|
|
654
|
+
if (error.isRetryable) {
|
|
655
|
+
// Schedule retry
|
|
656
|
+
}
|
|
657
|
+
}
|
|
658
|
+
}
|
|
659
|
+
```
|
|
660
|
+
|
|
661
|
+
**Error Codes:**
|
|
662
|
+
|
|
663
|
+
| Code | Retryable | Description |
|
|
664
|
+
|------|-----------|-------------|
|
|
665
|
+
| `timeout` | ✅ | Request timed out |
|
|
666
|
+
| `network_error` | ✅ | Network connectivity issue |
|
|
667
|
+
| `connection_failed` | ✅ | WebSocket connection failed |
|
|
668
|
+
| `websocket_error` | ✅ | WebSocket protocol error |
|
|
669
|
+
| `server_error` | ✅ (5xx only) | Server returned error |
|
|
670
|
+
| `not_connected` | ❌ | Client not connected |
|
|
671
|
+
| `encoding_error` | ❌ | Failed to encode request |
|
|
672
|
+
| `decoding_error` | ❌ | Failed to decode response |
|
|
673
|
+
| `cancelled` | ❌ | Request was cancelled |
|
|
674
|
+
|
|
675
|
+
### withRetry() - Generic Retry Utility
|
|
676
|
+
|
|
677
|
+
For custom retry logic outside of RPC:
|
|
678
|
+
|
|
679
|
+
```tsx
|
|
680
|
+
import { withRetry, RPCError } from '@djangocfg/centrifugo';
|
|
681
|
+
|
|
682
|
+
const result = await withRetry(
|
|
683
|
+
() => fetchSomething(),
|
|
684
|
+
{
|
|
685
|
+
maxRetries: 3,
|
|
686
|
+
baseDelayMs: 1000,
|
|
687
|
+
maxDelayMs: 10000,
|
|
688
|
+
jitterFactor: 0.2, // ±20% randomization
|
|
689
|
+
},
|
|
690
|
+
(state, delay) => {
|
|
691
|
+
console.log(`Retry ${state.attempt}, waiting ${delay}ms`);
|
|
692
|
+
}
|
|
693
|
+
);
|
|
694
|
+
```
|
|
695
|
+
|
|
601
696
|
### checkApiVersion() - API Contract Validation
|
|
602
697
|
|
|
603
698
|
Validates that the client API version matches the server. Useful for detecting when the frontend needs to refresh after a backend deployment.
|
|
@@ -1087,6 +1182,12 @@ import type {
|
|
|
1087
1182
|
RPCOptions,
|
|
1088
1183
|
RetryOptions,
|
|
1089
1184
|
VersionCheckResult,
|
|
1185
|
+
NamedRPCWithRetryOptions,
|
|
1186
|
+
|
|
1187
|
+
// Errors
|
|
1188
|
+
RPCErrorCode,
|
|
1189
|
+
RetryConfig,
|
|
1190
|
+
RetryState,
|
|
1090
1191
|
|
|
1091
1192
|
// Connection
|
|
1092
1193
|
ConnectionState,
|
|
@@ -1121,6 +1222,9 @@ import type {
|
|
|
1121
1222
|
SubscriptionsListProps,
|
|
1122
1223
|
CentrifugoMonitorProps,
|
|
1123
1224
|
} from '@djangocfg/centrifugo';
|
|
1225
|
+
|
|
1226
|
+
// Error classes
|
|
1227
|
+
import { RPCError, withRetry, createRetryHandler } from '@djangocfg/centrifugo';
|
|
1124
1228
|
```
|
|
1125
1229
|
|
|
1126
1230
|
## Unified Event System
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@djangocfg/centrifugo",
|
|
3
|
-
"version": "2.1.
|
|
3
|
+
"version": "2.1.73",
|
|
4
4
|
"description": "Production-ready Centrifugo WebSocket client for React with real-time subscriptions, RPC patterns, and connection state management",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"centrifugo",
|
|
@@ -51,9 +51,9 @@
|
|
|
51
51
|
"centrifuge": "^5.2.2"
|
|
52
52
|
},
|
|
53
53
|
"peerDependencies": {
|
|
54
|
-
"@djangocfg/api": "^2.1.
|
|
55
|
-
"@djangocfg/ui-nextjs": "^2.1.
|
|
56
|
-
"@djangocfg/layouts": "^2.1.
|
|
54
|
+
"@djangocfg/api": "^2.1.73",
|
|
55
|
+
"@djangocfg/ui-nextjs": "^2.1.73",
|
|
56
|
+
"@djangocfg/layouts": "^2.1.73",
|
|
57
57
|
"consola": "^3.4.2",
|
|
58
58
|
"lucide-react": "^0.545.0",
|
|
59
59
|
"moment": "^2.30.1",
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
"react-dom": "^19.1.0"
|
|
62
62
|
},
|
|
63
63
|
"devDependencies": {
|
|
64
|
-
"@djangocfg/typescript-config": "^2.1.
|
|
64
|
+
"@djangocfg/typescript-config": "^2.1.73",
|
|
65
65
|
"@types/react": "^19.1.0",
|
|
66
66
|
"@types/react-dom": "^19.1.0",
|
|
67
67
|
"moment": "^2.30.1",
|
|
@@ -47,7 +47,9 @@ import {
|
|
|
47
47
|
rpc as legacyRpc,
|
|
48
48
|
namedRPC as nativeNamedRPC,
|
|
49
49
|
namedRPCNoWait as nativeNamedRPCNoWait,
|
|
50
|
+
namedRPCWithRetry as nativeNamedRPCWithRetry,
|
|
50
51
|
type RPCManager,
|
|
52
|
+
type NamedRPCWithRetryOptions,
|
|
51
53
|
} from './rpc';
|
|
52
54
|
|
|
53
55
|
import { checkApiVersion as checkVersion } from './version';
|
|
@@ -158,6 +160,14 @@ export class CentrifugoRPCClient {
|
|
|
158
160
|
nativeNamedRPCNoWait(this.rpcManager, method, data, options);
|
|
159
161
|
}
|
|
160
162
|
|
|
163
|
+
async namedRPCWithRetry<TRequest = any, TResponse = any>(
|
|
164
|
+
method: string,
|
|
165
|
+
data: TRequest,
|
|
166
|
+
options?: NamedRPCWithRetryOptions
|
|
167
|
+
): Promise<TResponse> {
|
|
168
|
+
return nativeNamedRPCWithRetry(this.rpcManager, method, data, options);
|
|
169
|
+
}
|
|
170
|
+
|
|
161
171
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|
|
162
172
|
// API Version Checking
|
|
163
173
|
// ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
|