@jackchuka/gql-ingest 1.1.0 ā 1.3.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 +125 -20
- package/bin/cli.js +44 -41
- package/dist/config.d.ts +12 -2
- package/dist/config.d.ts.map +1 -1
- package/dist/graphql-client.d.ts +6 -2
- package/dist/graphql-client.d.ts.map +1 -1
- package/dist/mapper.d.ts +2 -2
- package/dist/mapper.d.ts.map +1 -1
- package/dist/metrics.d.ts +5 -0
- package/dist/metrics.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/cli.ts +24 -22
- package/src/config.test.ts +74 -7
- package/src/config.ts +37 -4
- package/src/graphql-client.test.ts +127 -1
- package/src/graphql-client.ts +132 -32
- package/src/mapper.test.ts +4 -4
- package/src/mapper.ts +13 -8
- package/src/metrics.ts +22 -0
package/src/mapper.ts
CHANGED
|
@@ -3,7 +3,7 @@ import path from "path";
|
|
|
3
3
|
import { readCsvFile, CsvRow } from "./csv-reader";
|
|
4
4
|
import { GraphQLClientWrapper } from "./graphql-client";
|
|
5
5
|
import { MetricsCollector } from "./metrics";
|
|
6
|
-
import { ParallelProcessingConfig } from "./config";
|
|
6
|
+
import { ParallelProcessingConfig, RetryConfig } from "./config";
|
|
7
7
|
|
|
8
8
|
export interface MappingConfig {
|
|
9
9
|
csvFile: string;
|
|
@@ -48,7 +48,8 @@ export class DataMapper {
|
|
|
48
48
|
|
|
49
49
|
async processEntity(
|
|
50
50
|
configPath: string,
|
|
51
|
-
parallelConfig?: ParallelProcessingConfig
|
|
51
|
+
parallelConfig?: ParallelProcessingConfig,
|
|
52
|
+
retryConfig?: RetryConfig
|
|
52
53
|
): Promise<void> {
|
|
53
54
|
const entityName = path.basename(configPath, ".json");
|
|
54
55
|
console.log(`Processing entity: ${configPath}`);
|
|
@@ -79,14 +80,16 @@ export class DataMapper {
|
|
|
79
80
|
mutation,
|
|
80
81
|
config.mapping,
|
|
81
82
|
entityName,
|
|
82
|
-
parallelConfig
|
|
83
|
+
parallelConfig,
|
|
84
|
+
retryConfig
|
|
83
85
|
);
|
|
84
86
|
} else {
|
|
85
87
|
await this.processRowsSequentially(
|
|
86
88
|
csvData,
|
|
87
89
|
mutation,
|
|
88
90
|
config.mapping,
|
|
89
|
-
entityName
|
|
91
|
+
entityName,
|
|
92
|
+
retryConfig
|
|
90
93
|
);
|
|
91
94
|
}
|
|
92
95
|
|
|
@@ -97,7 +100,8 @@ export class DataMapper {
|
|
|
97
100
|
csvData: CsvRow[],
|
|
98
101
|
mutation: string,
|
|
99
102
|
mapping: Record<string, string>,
|
|
100
|
-
entityName: string
|
|
103
|
+
entityName: string,
|
|
104
|
+
retryConfig?: RetryConfig
|
|
101
105
|
): Promise<void> {
|
|
102
106
|
const totalRows = csvData.length;
|
|
103
107
|
|
|
@@ -106,7 +110,7 @@ export class DataMapper {
|
|
|
106
110
|
const variables = this.mapCsvRowToVariables(row, mapping);
|
|
107
111
|
|
|
108
112
|
try {
|
|
109
|
-
await this.client.executeMutation(mutation, variables);
|
|
113
|
+
await this.client.executeMutation(mutation, variables, retryConfig);
|
|
110
114
|
this.metrics.recordSuccess(entityName);
|
|
111
115
|
|
|
112
116
|
// Show progress every 10% or at the end (only in non-verbose mode)
|
|
@@ -128,7 +132,8 @@ export class DataMapper {
|
|
|
128
132
|
mutation: string,
|
|
129
133
|
mapping: Record<string, string>,
|
|
130
134
|
entityName: string,
|
|
131
|
-
parallelConfig: ParallelProcessingConfig
|
|
135
|
+
parallelConfig: ParallelProcessingConfig,
|
|
136
|
+
retryConfig?: RetryConfig
|
|
132
137
|
): Promise<void> {
|
|
133
138
|
const concurrency = parallelConfig.concurrency;
|
|
134
139
|
console.log(
|
|
@@ -146,7 +151,7 @@ export class DataMapper {
|
|
|
146
151
|
const variables = this.mapCsvRowToVariables(row, mapping);
|
|
147
152
|
|
|
148
153
|
try {
|
|
149
|
-
const result = await this.client.executeMutation(mutation, variables);
|
|
154
|
+
const result = await this.client.executeMutation(mutation, variables, retryConfig);
|
|
150
155
|
this.metrics.recordSuccess(entityName);
|
|
151
156
|
return { success: true, result, row };
|
|
152
157
|
} catch (error) {
|
package/src/metrics.ts
CHANGED
|
@@ -12,6 +12,9 @@ export interface ProcessingMetrics {
|
|
|
12
12
|
totalFailures: number;
|
|
13
13
|
entityMetrics: Map<string, EntityMetrics>;
|
|
14
14
|
requestDurations: number[];
|
|
15
|
+
retryAttempts: number;
|
|
16
|
+
retrySuccesses: number;
|
|
17
|
+
retryFailures: number;
|
|
15
18
|
startTime: number;
|
|
16
19
|
endTime?: number;
|
|
17
20
|
}
|
|
@@ -26,6 +29,9 @@ export class MetricsCollector {
|
|
|
26
29
|
totalFailures: 0,
|
|
27
30
|
entityMetrics: new Map(),
|
|
28
31
|
requestDurations: [],
|
|
32
|
+
retryAttempts: 0,
|
|
33
|
+
retrySuccesses: 0,
|
|
34
|
+
retryFailures: 0,
|
|
29
35
|
startTime: Date.now(),
|
|
30
36
|
};
|
|
31
37
|
}
|
|
@@ -88,6 +94,16 @@ export class MetricsCollector {
|
|
|
88
94
|
this.metrics.requestDurations.push(duration);
|
|
89
95
|
}
|
|
90
96
|
|
|
97
|
+
recordRetrySuccess(attempts: number): void {
|
|
98
|
+
this.metrics.retryAttempts += attempts;
|
|
99
|
+
this.metrics.retrySuccesses++;
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
recordRetryFailure(attempts: number): void {
|
|
103
|
+
this.metrics.retryAttempts += attempts;
|
|
104
|
+
this.metrics.retryFailures++;
|
|
105
|
+
}
|
|
106
|
+
|
|
91
107
|
getAverageRequestDuration(): number {
|
|
92
108
|
if (this.metrics.requestDurations.length === 0) return 0;
|
|
93
109
|
const sum = this.metrics.requestDurations.reduce((a, b) => a + b, 0);
|
|
@@ -114,6 +130,12 @@ export class MetricsCollector {
|
|
|
114
130
|
if (this.metrics.requestDurations.length > 0) {
|
|
115
131
|
summary += ` Avg Request Time: ${avgRequestDuration.toFixed(0)}ms\n`;
|
|
116
132
|
}
|
|
133
|
+
|
|
134
|
+
if (this.metrics.retryAttempts > 0) {
|
|
135
|
+
summary += ` Retry Attempts: ${this.metrics.retryAttempts}\n`;
|
|
136
|
+
summary += ` Retry Successes: ${this.metrics.retrySuccesses}\n`;
|
|
137
|
+
summary += ` Retry Failures: ${this.metrics.retryFailures}\n`;
|
|
138
|
+
}
|
|
117
139
|
|
|
118
140
|
if (this.metrics.entityMetrics.size > 1) {
|
|
119
141
|
summary += `\nš Per-Entity Breakdown:\n`;
|