@jackchuka/gql-ingest 2.0.2 → 2.2.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 +7 -7
- package/bin/cli.js +72 -66
- package/dist/config.d.ts.map +1 -1
- package/dist/dependency-resolver.d.ts.map +1 -1
- package/dist/graphql-client.d.ts.map +1 -1
- package/dist/mapper.d.ts +1 -1
- package/dist/mapper.d.ts.map +1 -1
- package/dist/metrics.d.ts.map +1 -1
- package/dist/readers/data-reader.d.ts.map +1 -1
- package/dist/readers/json.d.ts.map +1 -1
- package/dist/readers/jsonl.d.ts.map +1 -1
- package/dist/readers/yaml.d.ts.map +1 -1
- package/package.json +32 -26
- package/src/cli.ts +0 -187
- package/src/config.test.ts +0 -272
- package/src/config.ts +0 -125
- package/src/dependency-resolver.test.ts +0 -211
- package/src/dependency-resolver.ts +0 -102
- package/src/graphql-client.test.ts +0 -219
- package/src/graphql-client.ts +0 -151
- package/src/mapper.test.ts +0 -607
- package/src/mapper.ts +0 -489
- package/src/metrics.test.ts +0 -207
- package/src/metrics.ts +0 -161
- package/src/readers/csv.test.ts +0 -82
- package/src/readers/csv.ts +0 -29
- package/src/readers/data-reader.test.ts +0 -104
- package/src/readers/data-reader.ts +0 -61
- package/src/readers/index.ts +0 -18
- package/src/readers/json.test.ts +0 -80
- package/src/readers/json.ts +0 -27
- package/src/readers/jsonl.test.ts +0 -96
- package/src/readers/jsonl.ts +0 -28
- package/src/readers/yaml.test.ts +0 -95
- package/src/readers/yaml.ts +0 -28
package/src/graphql-client.ts
DELETED
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
import { GraphQLClient } from "graphql-request";
|
|
2
|
-
import { MetricsCollector } from "./metrics";
|
|
3
|
-
import { DEFAULT_RETRY_CONFIG, RetryConfig } from "./config";
|
|
4
|
-
|
|
5
|
-
export class GraphQLClientWrapper {
|
|
6
|
-
private client: GraphQLClient;
|
|
7
|
-
private metrics?: MetricsCollector;
|
|
8
|
-
private verbose: boolean;
|
|
9
|
-
|
|
10
|
-
constructor(
|
|
11
|
-
endpoint: string,
|
|
12
|
-
headers?: Record<string, string>,
|
|
13
|
-
metrics?: MetricsCollector,
|
|
14
|
-
verbose: boolean = false
|
|
15
|
-
) {
|
|
16
|
-
this.client = new GraphQLClient(endpoint, {
|
|
17
|
-
headers: headers || {},
|
|
18
|
-
});
|
|
19
|
-
this.metrics = metrics;
|
|
20
|
-
this.verbose = verbose;
|
|
21
|
-
}
|
|
22
|
-
|
|
23
|
-
async executeMutation(
|
|
24
|
-
mutation: string,
|
|
25
|
-
variables: Record<string, any>,
|
|
26
|
-
retryConfig?: RetryConfig
|
|
27
|
-
): Promise<any> {
|
|
28
|
-
const config = retryConfig || DEFAULT_RETRY_CONFIG;
|
|
29
|
-
|
|
30
|
-
let lastError: any;
|
|
31
|
-
const totalStartTime = Date.now();
|
|
32
|
-
|
|
33
|
-
for (let attempt = 0; attempt < config.maxAttempts; attempt++) {
|
|
34
|
-
const attemptStartTime = Date.now();
|
|
35
|
-
|
|
36
|
-
try {
|
|
37
|
-
const result = await this.client.request(mutation, variables);
|
|
38
|
-
|
|
39
|
-
if (this.metrics) {
|
|
40
|
-
const duration = Date.now() - attemptStartTime;
|
|
41
|
-
this.metrics.recordRequestDuration(duration);
|
|
42
|
-
if (attempt > 0) {
|
|
43
|
-
this.metrics.recordRetrySuccess(attempt);
|
|
44
|
-
}
|
|
45
|
-
}
|
|
46
|
-
|
|
47
|
-
if (this.verbose) {
|
|
48
|
-
const totalDuration = Date.now() - totalStartTime;
|
|
49
|
-
const retryInfo =
|
|
50
|
-
attempt > 0 ? ` (succeeded on attempt ${attempt + 1})` : "";
|
|
51
|
-
console.log(
|
|
52
|
-
`✓ GraphQL request completed in ${totalDuration}ms${retryInfo}:`,
|
|
53
|
-
result
|
|
54
|
-
);
|
|
55
|
-
}
|
|
56
|
-
|
|
57
|
-
return result;
|
|
58
|
-
} catch (error: any) {
|
|
59
|
-
lastError = error;
|
|
60
|
-
const duration = Date.now() - attemptStartTime;
|
|
61
|
-
|
|
62
|
-
if (this.metrics) {
|
|
63
|
-
this.metrics.recordRequestDuration(duration);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
// Check if this is the last attempt
|
|
67
|
-
if (attempt === config.maxAttempts - 1) {
|
|
68
|
-
if (this.metrics && attempt > 0) {
|
|
69
|
-
this.metrics.recordRetryFailure(attempt);
|
|
70
|
-
}
|
|
71
|
-
break;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
// Check if error is retryable
|
|
75
|
-
if (!this.isRetryableError(error, config)) {
|
|
76
|
-
if (this.verbose) {
|
|
77
|
-
console.error(
|
|
78
|
-
`✗ GraphQL request failed with non-retryable error in ${duration}ms:`,
|
|
79
|
-
error
|
|
80
|
-
);
|
|
81
|
-
} else {
|
|
82
|
-
console.error("GraphQL mutation failed (non-retryable):", error);
|
|
83
|
-
}
|
|
84
|
-
throw error;
|
|
85
|
-
}
|
|
86
|
-
|
|
87
|
-
// Calculate delay
|
|
88
|
-
const delay = this.calculateDelay(attempt, config);
|
|
89
|
-
|
|
90
|
-
if (this.verbose) {
|
|
91
|
-
console.log(
|
|
92
|
-
`⏳ GraphQL request failed (attempt ${attempt + 1}/${
|
|
93
|
-
config.maxAttempts
|
|
94
|
-
}), retrying in ${delay}ms...`
|
|
95
|
-
);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
// Wait before retry
|
|
99
|
-
await this.sleep(delay);
|
|
100
|
-
}
|
|
101
|
-
}
|
|
102
|
-
|
|
103
|
-
// All retries exhausted
|
|
104
|
-
if (this.verbose) {
|
|
105
|
-
const totalDuration = Date.now() - totalStartTime;
|
|
106
|
-
console.error(
|
|
107
|
-
`✗ GraphQL request failed after ${config.maxAttempts} attempts in ${totalDuration}ms:`,
|
|
108
|
-
lastError
|
|
109
|
-
);
|
|
110
|
-
} else {
|
|
111
|
-
console.error(
|
|
112
|
-
`GraphQL mutation failed after ${config.maxAttempts} attempts:`,
|
|
113
|
-
lastError
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
|
-
throw lastError;
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
private isRetryableError(error: any, config: RetryConfig): boolean {
|
|
121
|
-
// Network errors (no response)
|
|
122
|
-
if (!error.response) {
|
|
123
|
-
return true;
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
// Check HTTP status codes
|
|
127
|
-
const status = error.response.status;
|
|
128
|
-
return config.retryableStatusCodes.includes(status);
|
|
129
|
-
}
|
|
130
|
-
|
|
131
|
-
private calculateDelay(attempt: number, config: RetryConfig): number {
|
|
132
|
-
if (!config.exponentialBackoff) {
|
|
133
|
-
return config.baseDelay;
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
const exponentialDelay = config.baseDelay * Math.pow(2, attempt);
|
|
137
|
-
const cappedDelay = Math.min(exponentialDelay, config.maxDelay);
|
|
138
|
-
|
|
139
|
-
// Add jitter (±20% randomization)
|
|
140
|
-
const jitter = cappedDelay * 0.2 * (Math.random() - 0.5);
|
|
141
|
-
return Math.max(0, cappedDelay + jitter);
|
|
142
|
-
}
|
|
143
|
-
|
|
144
|
-
private sleep(ms: number): Promise<void> {
|
|
145
|
-
return new Promise((resolve) => setTimeout(resolve, ms));
|
|
146
|
-
}
|
|
147
|
-
|
|
148
|
-
setHeaders(headers: Record<string, string>) {
|
|
149
|
-
this.client.setHeaders(headers);
|
|
150
|
-
}
|
|
151
|
-
}
|