adaptic-backend 1.0.340 → 1.0.341
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/Account.cjs +2543 -2265
- package/Account.d.ts +19 -2
- package/Action.cjs +1116 -838
- package/Action.d.ts +19 -2
- package/Alert.cjs +2626 -2348
- package/Alert.d.ts +19 -2
- package/Allocation.cjs +2578 -2300
- package/Allocation.d.ts +19 -2
- package/AlpacaAccount.cjs +2383 -2105
- package/AlpacaAccount.d.ts +19 -2
- package/Asset.cjs +1813 -1535
- package/Asset.d.ts +19 -2
- package/Authenticator.cjs +2568 -2290
- package/Authenticator.d.ts +19 -2
- package/Customer.cjs +2495 -2217
- package/Customer.d.ts +19 -2
- package/EconomicEvent.cjs +645 -367
- package/EconomicEvent.d.ts +19 -2
- package/MarketSentiment.cjs +618 -340
- package/MarketSentiment.d.ts +19 -2
- package/NewsArticle.cjs +1933 -1655
- package/NewsArticle.d.ts +19 -2
- package/NewsArticleAssetSentiment.cjs +1842 -1564
- package/NewsArticleAssetSentiment.d.ts +19 -2
- package/ScheduledOptionOrder.cjs +594 -316
- package/ScheduledOptionOrder.d.ts +19 -2
- package/Session.cjs +2570 -2292
- package/Session.d.ts +19 -2
- package/Trade.cjs +1073 -795
- package/Trade.d.ts +19 -2
- package/User.cjs +2288 -2010
- package/User.d.ts +19 -2
- package/VerificationToken.cjs +606 -328
- package/VerificationToken.d.ts +19 -2
- package/esm/Account.d.ts +19 -2
- package/esm/Account.d.ts.map +1 -1
- package/esm/Account.js.map +1 -1
- package/esm/Account.mjs +2534 -2263
- package/esm/Action.d.ts +19 -2
- package/esm/Action.d.ts.map +1 -1
- package/esm/Action.js.map +1 -1
- package/esm/Action.mjs +1107 -836
- package/esm/Alert.d.ts +19 -2
- package/esm/Alert.d.ts.map +1 -1
- package/esm/Alert.js.map +1 -1
- package/esm/Alert.mjs +2617 -2346
- package/esm/Allocation.d.ts +19 -2
- package/esm/Allocation.d.ts.map +1 -1
- package/esm/Allocation.js.map +1 -1
- package/esm/Allocation.mjs +2569 -2298
- package/esm/AlpacaAccount.d.ts +19 -2
- package/esm/AlpacaAccount.d.ts.map +1 -1
- package/esm/AlpacaAccount.js.map +1 -1
- package/esm/AlpacaAccount.mjs +2374 -2103
- package/esm/Asset.d.ts +19 -2
- package/esm/Asset.d.ts.map +1 -1
- package/esm/Asset.js.map +1 -1
- package/esm/Asset.mjs +1804 -1533
- package/esm/Authenticator.d.ts +19 -2
- package/esm/Authenticator.d.ts.map +1 -1
- package/esm/Authenticator.js.map +1 -1
- package/esm/Authenticator.mjs +2559 -2288
- package/esm/Customer.d.ts +19 -2
- package/esm/Customer.d.ts.map +1 -1
- package/esm/Customer.js.map +1 -1
- package/esm/Customer.mjs +2486 -2215
- package/esm/EconomicEvent.d.ts +19 -2
- package/esm/EconomicEvent.d.ts.map +1 -1
- package/esm/EconomicEvent.js.map +1 -1
- package/esm/EconomicEvent.mjs +636 -365
- package/esm/MarketSentiment.d.ts +19 -2
- package/esm/MarketSentiment.d.ts.map +1 -1
- package/esm/MarketSentiment.js.map +1 -1
- package/esm/MarketSentiment.mjs +609 -338
- package/esm/NewsArticle.d.ts +19 -2
- package/esm/NewsArticle.d.ts.map +1 -1
- package/esm/NewsArticle.js.map +1 -1
- package/esm/NewsArticle.mjs +1924 -1653
- package/esm/NewsArticleAssetSentiment.d.ts +19 -2
- package/esm/NewsArticleAssetSentiment.d.ts.map +1 -1
- package/esm/NewsArticleAssetSentiment.js.map +1 -1
- package/esm/NewsArticleAssetSentiment.mjs +1833 -1562
- package/esm/ScheduledOptionOrder.d.ts +19 -2
- package/esm/ScheduledOptionOrder.d.ts.map +1 -1
- package/esm/ScheduledOptionOrder.js.map +1 -1
- package/esm/ScheduledOptionOrder.mjs +585 -314
- package/esm/Session.d.ts +19 -2
- package/esm/Session.d.ts.map +1 -1
- package/esm/Session.js.map +1 -1
- package/esm/Session.mjs +2561 -2290
- package/esm/Trade.d.ts +19 -2
- package/esm/Trade.d.ts.map +1 -1
- package/esm/Trade.js.map +1 -1
- package/esm/Trade.mjs +1064 -793
- package/esm/User.d.ts +19 -2
- package/esm/User.d.ts.map +1 -1
- package/esm/User.js.map +1 -1
- package/esm/User.mjs +2279 -2008
- package/esm/VerificationToken.d.ts +19 -2
- package/esm/VerificationToken.d.ts.map +1 -1
- package/esm/VerificationToken.js.map +1 -1
- package/esm/VerificationToken.mjs +597 -326
- package/esm/prismaClient.d.ts +4 -5
- package/esm/prismaClient.d.ts.map +1 -1
- package/esm/prismaClient.js.map +1 -1
- package/esm/prismaClient.mjs +13 -11
- package/package.json +1 -1
- package/prismaClient.cjs +13 -11
- package/prismaClient.d.ts +4 -5
- package/server.cjs +37 -5
package/esm/Action.mjs
CHANGED
@@ -24,937 +24,1208 @@ export const Action = {
|
|
24
24
|
* @param client - Apollo Client instance.
|
25
25
|
* @returns The created Action or null.
|
26
26
|
*/
|
27
|
+
/**
|
28
|
+
* Create a new Action record.
|
29
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
30
|
+
* @param props - Properties for the new record.
|
31
|
+
* @param globalClient - Apollo Client instance.
|
32
|
+
* @returns The created Action or null.
|
33
|
+
*/
|
27
34
|
async create(props, globalClient) {
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
?
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
:
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
}
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
35
|
+
// Maximum number of retries for database connection issues
|
36
|
+
const MAX_RETRIES = 3;
|
37
|
+
let retryCount = 0;
|
38
|
+
let lastError = null;
|
39
|
+
// Retry loop to handle potential database connection issues
|
40
|
+
while (retryCount < MAX_RETRIES) {
|
41
|
+
try {
|
42
|
+
const [modules, client] = await Promise.all([
|
43
|
+
getApolloModules(),
|
44
|
+
globalClient
|
45
|
+
? Promise.resolve(globalClient)
|
46
|
+
: importedClient
|
47
|
+
]);
|
48
|
+
const { gql, ApolloError } = modules;
|
49
|
+
const CREATE_ONE_ACTION = gql `
|
50
|
+
mutation createOneAction($data: ActionCreateInput!) {
|
51
|
+
createOneAction(data: $data) {
|
52
|
+
${selectionSet}
|
53
|
+
}
|
54
|
+
}
|
55
|
+
`;
|
56
|
+
const variables = {
|
57
|
+
data: {
|
58
|
+
sequence: props.sequence !== undefined ? props.sequence : undefined,
|
59
|
+
type: props.type !== undefined ? props.type : undefined,
|
60
|
+
primary: props.primary !== undefined ? props.primary : undefined,
|
61
|
+
note: props.note !== undefined ? props.note : undefined,
|
62
|
+
status: props.status !== undefined ? props.status : undefined,
|
63
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
64
|
+
trade: props.trade ?
|
65
|
+
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && Object.keys(props.trade)[0] === 'id'
|
66
|
+
? { connect: {
|
67
|
+
id: props.trade.id
|
68
|
+
}
|
69
|
+
}
|
70
|
+
: { connectOrCreate: {
|
71
|
+
where: {
|
72
|
+
id: props.trade.id !== undefined ? props.trade.id : undefined,
|
73
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
74
|
+
equals: props.trade.alpacaAccountId
|
75
|
+
} : undefined,
|
76
|
+
symbol: props.trade.symbol !== undefined ? {
|
77
|
+
equals: props.trade.symbol
|
78
|
+
} : undefined,
|
79
|
+
},
|
80
|
+
create: {
|
81
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
82
|
+
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
83
|
+
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
84
|
+
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
85
|
+
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
86
|
+
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
87
|
+
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
88
|
+
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
89
|
+
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
90
|
+
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
91
|
+
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
92
|
+
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
93
|
+
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
94
|
+
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
95
|
+
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
96
|
+
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
97
|
+
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
98
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
99
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
100
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
101
|
+
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
102
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
103
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
104
|
+
},
|
105
|
+
}
|
106
|
+
} : undefined,
|
107
|
+
},
|
108
|
+
};
|
109
|
+
const filteredVariables = removeUndefinedProps(variables);
|
110
|
+
const response = await client.mutate({
|
111
|
+
mutation: CREATE_ONE_ACTION,
|
112
|
+
variables: filteredVariables,
|
113
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
114
|
+
fetchPolicy: 'no-cache'
|
115
|
+
});
|
116
|
+
if (response.errors && response.errors.length > 0)
|
117
|
+
throw new Error(response.errors[0].message);
|
118
|
+
if (response && response.data && response.data.createOneAction) {
|
119
|
+
return response.data.createOneAction;
|
120
|
+
}
|
121
|
+
else {
|
122
|
+
return null;
|
123
|
+
}
|
102
124
|
}
|
103
|
-
|
104
|
-
|
125
|
+
catch (error) {
|
126
|
+
lastError = error;
|
127
|
+
// Check if this is a database connection error that we should retry
|
128
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
129
|
+
error.message?.includes('Cannot reach database server') ||
|
130
|
+
error.message?.includes('Connection timed out') ||
|
131
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
132
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
133
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
134
|
+
retryCount++;
|
135
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
136
|
+
console.warn("Database connection error, retrying...");
|
137
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
138
|
+
continue;
|
139
|
+
}
|
140
|
+
// Log the error and rethrow
|
141
|
+
console.error("Database error occurred:", error);
|
142
|
+
throw error;
|
105
143
|
}
|
106
144
|
}
|
107
|
-
|
108
|
-
|
109
|
-
throw error;
|
110
|
-
}
|
145
|
+
// If we exhausted retries, throw the last error
|
146
|
+
throw lastError;
|
111
147
|
},
|
112
148
|
/**
|
113
149
|
* Create multiple Action records.
|
150
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
114
151
|
* @param props - Array of Action objects for the new records.
|
115
152
|
* @param globalClient - Apollo Client instance.
|
116
153
|
* @returns The count of created records or null.
|
117
154
|
*/
|
118
155
|
async createMany(props, globalClient) {
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
primary: prop.primary !== undefined ? prop.primary : undefined,
|
138
|
-
note: prop.note !== undefined ? prop.note : undefined,
|
139
|
-
status: prop.status !== undefined ? prop.status : undefined,
|
140
|
-
alpacaOrderId: prop.alpacaOrderId !== undefined ? prop.alpacaOrderId : undefined,
|
141
|
-
})),
|
142
|
-
};
|
143
|
-
const filteredVariables = removeUndefinedProps(variables);
|
144
|
-
try {
|
145
|
-
const response = await client.mutate({ mutation: CREATE_MANY_ACTION, variables: filteredVariables });
|
146
|
-
if (response.errors && response.errors.length > 0)
|
147
|
-
throw new Error(response.errors[0].message);
|
148
|
-
if (response && response.data && response.data.createManyAction) {
|
149
|
-
return response.data.createManyAction;
|
156
|
+
// Maximum number of retries for database connection issues
|
157
|
+
const MAX_RETRIES = 3;
|
158
|
+
let retryCount = 0;
|
159
|
+
let lastError = null;
|
160
|
+
// Retry loop to handle potential database connection issues
|
161
|
+
while (retryCount < MAX_RETRIES) {
|
162
|
+
try {
|
163
|
+
const [modules, client] = await Promise.all([
|
164
|
+
getApolloModules(),
|
165
|
+
globalClient
|
166
|
+
? Promise.resolve(globalClient)
|
167
|
+
: importedClient
|
168
|
+
]);
|
169
|
+
const { gql, ApolloError } = modules;
|
170
|
+
const CREATE_MANY_ACTION = gql `
|
171
|
+
mutation createManyAction($data: [ActionCreateManyInput!]!) {
|
172
|
+
createManyAction(data: $data) {
|
173
|
+
count
|
150
174
|
}
|
151
|
-
|
152
|
-
|
175
|
+
}`;
|
176
|
+
const variables = {
|
177
|
+
data: props.map(prop => ({
|
178
|
+
sequence: prop.sequence !== undefined ? prop.sequence : undefined,
|
179
|
+
tradeId: prop.tradeId !== undefined ? prop.tradeId : undefined,
|
180
|
+
type: prop.type !== undefined ? prop.type : undefined,
|
181
|
+
primary: prop.primary !== undefined ? prop.primary : undefined,
|
182
|
+
note: prop.note !== undefined ? prop.note : undefined,
|
183
|
+
status: prop.status !== undefined ? prop.status : undefined,
|
184
|
+
alpacaOrderId: prop.alpacaOrderId !== undefined ? prop.alpacaOrderId : undefined,
|
185
|
+
})),
|
186
|
+
};
|
187
|
+
const filteredVariables = removeUndefinedProps(variables);
|
188
|
+
const response = await client.mutate({
|
189
|
+
mutation: CREATE_MANY_ACTION,
|
190
|
+
variables: filteredVariables,
|
191
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
192
|
+
fetchPolicy: 'no-cache'
|
193
|
+
});
|
194
|
+
if (response.errors && response.errors.length > 0)
|
195
|
+
throw new Error(response.errors[0].message);
|
196
|
+
if (response && response.data && response.data.createManyAction) {
|
197
|
+
return response.data.createManyAction;
|
198
|
+
}
|
199
|
+
else {
|
200
|
+
return null;
|
201
|
+
}
|
202
|
+
}
|
203
|
+
catch (error) {
|
204
|
+
lastError = error;
|
205
|
+
// Check if this is a database connection error that we should retry
|
206
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
207
|
+
error.message?.includes('Cannot reach database server') ||
|
208
|
+
error.message?.includes('Connection timed out') ||
|
209
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
210
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
211
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
212
|
+
retryCount++;
|
213
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
214
|
+
console.warn("Database connection error, retrying...");
|
215
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
216
|
+
continue;
|
217
|
+
}
|
218
|
+
// Log the error and rethrow
|
219
|
+
console.error("Database error occurred:", error);
|
220
|
+
throw error;
|
153
221
|
}
|
154
222
|
}
|
155
|
-
|
156
|
-
|
157
|
-
throw error;
|
158
|
-
}
|
223
|
+
// If we exhausted retries, throw the last error
|
224
|
+
throw lastError;
|
159
225
|
},
|
160
226
|
/**
|
161
227
|
* Update a single Action record.
|
228
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
162
229
|
* @param props - Properties to update.
|
163
230
|
* @param globalClient - Apollo Client instance.
|
164
231
|
* @returns The updated Action or null.
|
165
232
|
*/
|
166
233
|
async update(props, globalClient) {
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
178
|
-
|
179
|
-
|
180
|
-
|
181
|
-
|
182
|
-
|
183
|
-
|
184
|
-
|
185
|
-
equals: props.tradeId
|
186
|
-
} : undefined,
|
187
|
-
},
|
188
|
-
data: {
|
189
|
-
id: props.id !== undefined ? {
|
190
|
-
set: props.id
|
191
|
-
} : undefined,
|
192
|
-
sequence: props.sequence !== undefined ? {
|
193
|
-
set: props.sequence
|
194
|
-
} : undefined,
|
195
|
-
type: props.type !== undefined ? {
|
196
|
-
set: props.type
|
197
|
-
} : undefined,
|
198
|
-
primary: props.primary !== undefined ? {
|
199
|
-
set: props.primary
|
200
|
-
} : undefined,
|
201
|
-
note: props.note !== undefined ? {
|
202
|
-
set: props.note
|
203
|
-
} : undefined,
|
204
|
-
status: props.status !== undefined ? {
|
205
|
-
set: props.status
|
206
|
-
} : undefined,
|
207
|
-
createdAt: props.createdAt !== undefined ? {
|
208
|
-
set: props.createdAt
|
209
|
-
} : undefined,
|
210
|
-
updatedAt: props.updatedAt !== undefined ? {
|
211
|
-
set: props.updatedAt
|
212
|
-
} : undefined,
|
213
|
-
alpacaOrderId: props.alpacaOrderId !== undefined ? {
|
214
|
-
set: props.alpacaOrderId
|
215
|
-
} : undefined,
|
216
|
-
trade: props.trade ?
|
217
|
-
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && (Object.keys(props.trade)[0] === 'id' || Object.keys(props.trade)[0] === 'symbol')
|
218
|
-
? {
|
219
|
-
connect: {
|
220
|
-
id: props.trade.id
|
221
|
-
}
|
222
|
-
} : { upsert: {
|
223
|
-
where: {
|
224
|
-
id: props.trade.id !== undefined ? {
|
225
|
-
equals: props.trade.id
|
226
|
-
} : undefined,
|
227
|
-
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
228
|
-
equals: props.trade.alpacaAccountId
|
229
|
-
} : undefined,
|
230
|
-
symbol: props.trade.symbol !== undefined ? {
|
231
|
-
equals: props.trade.symbol
|
232
|
-
} : undefined,
|
233
|
-
},
|
234
|
-
update: {
|
235
|
-
id: props.trade.id !== undefined ? {
|
236
|
-
set: props.trade.id
|
237
|
-
} : undefined,
|
238
|
-
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
239
|
-
set: props.trade.alpacaAccountId
|
240
|
-
} : undefined,
|
241
|
-
signal: props.trade.signal !== undefined ? {
|
242
|
-
set: props.trade.signal
|
243
|
-
} : undefined,
|
244
|
-
strategy: props.trade.strategy !== undefined ? {
|
245
|
-
set: props.trade.strategy
|
246
|
-
} : undefined,
|
247
|
-
analysis: props.trade.analysis !== undefined ? {
|
248
|
-
set: props.trade.analysis
|
249
|
-
} : undefined,
|
250
|
-
summary: props.trade.summary !== undefined ? {
|
251
|
-
set: props.trade.summary
|
252
|
-
} : undefined,
|
253
|
-
confidence: props.trade.confidence !== undefined ? {
|
254
|
-
set: props.trade.confidence
|
255
|
-
} : undefined,
|
256
|
-
timestamp: props.trade.timestamp !== undefined ? {
|
257
|
-
set: props.trade.timestamp
|
258
|
-
} : undefined,
|
259
|
-
status: props.trade.status !== undefined ? {
|
260
|
-
set: props.trade.status
|
261
|
-
} : undefined,
|
262
|
-
symbol: props.trade.symbol !== undefined ? {
|
263
|
-
set: props.trade.symbol
|
264
|
-
} : undefined,
|
265
|
-
entryPrice: props.trade.entryPrice !== undefined ? {
|
266
|
-
set: props.trade.entryPrice
|
267
|
-
} : undefined,
|
268
|
-
exitPrice: props.trade.exitPrice !== undefined ? {
|
269
|
-
set: props.trade.exitPrice
|
270
|
-
} : undefined,
|
271
|
-
entryQty: props.trade.entryQty !== undefined ? {
|
272
|
-
set: props.trade.entryQty
|
273
|
-
} : undefined,
|
274
|
-
exitQty: props.trade.exitQty !== undefined ? {
|
275
|
-
set: props.trade.exitQty
|
276
|
-
} : undefined,
|
277
|
-
entryValue: props.trade.entryValue !== undefined ? {
|
278
|
-
set: props.trade.entryValue
|
279
|
-
} : undefined,
|
280
|
-
exitValue: props.trade.exitValue !== undefined ? {
|
281
|
-
set: props.trade.exitValue
|
282
|
-
} : undefined,
|
283
|
-
entryTime: props.trade.entryTime !== undefined ? {
|
284
|
-
set: props.trade.entryTime
|
285
|
-
} : undefined,
|
286
|
-
exitTime: props.trade.exitTime !== undefined ? {
|
287
|
-
set: props.trade.exitTime
|
288
|
-
} : undefined,
|
289
|
-
pnlAmount: props.trade.pnlAmount !== undefined ? {
|
290
|
-
set: props.trade.pnlAmount
|
291
|
-
} : undefined,
|
292
|
-
pnlPercent: props.trade.pnlPercent !== undefined ? {
|
293
|
-
set: props.trade.pnlPercent
|
294
|
-
} : undefined,
|
295
|
-
durationMinutes: props.trade.durationMinutes !== undefined ? {
|
296
|
-
set: props.trade.durationMinutes
|
297
|
-
} : undefined,
|
298
|
-
marketPhase: props.trade.marketPhase !== undefined ? {
|
299
|
-
set: props.trade.marketPhase
|
300
|
-
} : undefined,
|
301
|
-
marketVolatility: props.trade.marketVolatility !== undefined ? {
|
302
|
-
set: props.trade.marketVolatility
|
303
|
-
} : undefined,
|
304
|
-
thresholdsJson: props.trade.thresholdsJson !== undefined ? {
|
305
|
-
set: props.trade.thresholdsJson
|
306
|
-
} : undefined,
|
307
|
-
},
|
308
|
-
create: {
|
309
|
-
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
310
|
-
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
311
|
-
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
312
|
-
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
313
|
-
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
314
|
-
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
315
|
-
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
316
|
-
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
317
|
-
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
318
|
-
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
319
|
-
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
320
|
-
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
321
|
-
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
322
|
-
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
323
|
-
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
324
|
-
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
325
|
-
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
326
|
-
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
327
|
-
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
328
|
-
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
329
|
-
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
330
|
-
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
331
|
-
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
332
|
-
},
|
333
|
-
}
|
334
|
-
} : undefined,
|
335
|
-
},
|
336
|
-
};
|
337
|
-
const filteredVariables = removeUndefinedProps(variables);
|
338
|
-
try {
|
339
|
-
const response = await client.mutate({ mutation: UPDATE_ONE_ACTION, variables: filteredVariables });
|
340
|
-
if (response.errors && response.errors.length > 0)
|
341
|
-
throw new Error(response.errors[0].message);
|
342
|
-
if (response && response.data && response.data.updateOneAction) {
|
343
|
-
return response.data.updateOneAction;
|
234
|
+
// Maximum number of retries for database connection issues
|
235
|
+
const MAX_RETRIES = 3;
|
236
|
+
let retryCount = 0;
|
237
|
+
let lastError = null;
|
238
|
+
// Retry loop to handle potential database connection issues
|
239
|
+
while (retryCount < MAX_RETRIES) {
|
240
|
+
try {
|
241
|
+
const [modules, client] = await Promise.all([
|
242
|
+
getApolloModules(),
|
243
|
+
globalClient
|
244
|
+
? Promise.resolve(globalClient)
|
245
|
+
: importedClient
|
246
|
+
]);
|
247
|
+
const { gql, ApolloError } = modules;
|
248
|
+
const UPDATE_ONE_ACTION = gql `
|
249
|
+
mutation updateOneAction($data: ActionUpdateInput!, $where: ActionWhereUniqueInput!) {
|
250
|
+
updateOneAction(data: $data, where: $where) {
|
251
|
+
${selectionSet}
|
344
252
|
}
|
345
|
-
|
346
|
-
|
253
|
+
}`;
|
254
|
+
const variables = {
|
255
|
+
where: {
|
256
|
+
id: props.id !== undefined ? props.id : undefined,
|
257
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
258
|
+
tradeId: props.tradeId !== undefined ? {
|
259
|
+
equals: props.tradeId
|
260
|
+
} : undefined,
|
261
|
+
},
|
262
|
+
data: {
|
263
|
+
id: props.id !== undefined ? {
|
264
|
+
set: props.id
|
265
|
+
} : undefined,
|
266
|
+
sequence: props.sequence !== undefined ? {
|
267
|
+
set: props.sequence
|
268
|
+
} : undefined,
|
269
|
+
type: props.type !== undefined ? {
|
270
|
+
set: props.type
|
271
|
+
} : undefined,
|
272
|
+
primary: props.primary !== undefined ? {
|
273
|
+
set: props.primary
|
274
|
+
} : undefined,
|
275
|
+
note: props.note !== undefined ? {
|
276
|
+
set: props.note
|
277
|
+
} : undefined,
|
278
|
+
status: props.status !== undefined ? {
|
279
|
+
set: props.status
|
280
|
+
} : undefined,
|
281
|
+
createdAt: props.createdAt !== undefined ? {
|
282
|
+
set: props.createdAt
|
283
|
+
} : undefined,
|
284
|
+
updatedAt: props.updatedAt !== undefined ? {
|
285
|
+
set: props.updatedAt
|
286
|
+
} : undefined,
|
287
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? {
|
288
|
+
set: props.alpacaOrderId
|
289
|
+
} : undefined,
|
290
|
+
trade: props.trade ?
|
291
|
+
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && (Object.keys(props.trade)[0] === 'id' || Object.keys(props.trade)[0] === 'symbol')
|
292
|
+
? {
|
293
|
+
connect: {
|
294
|
+
id: props.trade.id
|
295
|
+
}
|
296
|
+
} : { upsert: {
|
297
|
+
where: {
|
298
|
+
id: props.trade.id !== undefined ? {
|
299
|
+
equals: props.trade.id
|
300
|
+
} : undefined,
|
301
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
302
|
+
equals: props.trade.alpacaAccountId
|
303
|
+
} : undefined,
|
304
|
+
symbol: props.trade.symbol !== undefined ? {
|
305
|
+
equals: props.trade.symbol
|
306
|
+
} : undefined,
|
307
|
+
},
|
308
|
+
update: {
|
309
|
+
id: props.trade.id !== undefined ? {
|
310
|
+
set: props.trade.id
|
311
|
+
} : undefined,
|
312
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
313
|
+
set: props.trade.alpacaAccountId
|
314
|
+
} : undefined,
|
315
|
+
signal: props.trade.signal !== undefined ? {
|
316
|
+
set: props.trade.signal
|
317
|
+
} : undefined,
|
318
|
+
strategy: props.trade.strategy !== undefined ? {
|
319
|
+
set: props.trade.strategy
|
320
|
+
} : undefined,
|
321
|
+
analysis: props.trade.analysis !== undefined ? {
|
322
|
+
set: props.trade.analysis
|
323
|
+
} : undefined,
|
324
|
+
summary: props.trade.summary !== undefined ? {
|
325
|
+
set: props.trade.summary
|
326
|
+
} : undefined,
|
327
|
+
confidence: props.trade.confidence !== undefined ? {
|
328
|
+
set: props.trade.confidence
|
329
|
+
} : undefined,
|
330
|
+
timestamp: props.trade.timestamp !== undefined ? {
|
331
|
+
set: props.trade.timestamp
|
332
|
+
} : undefined,
|
333
|
+
status: props.trade.status !== undefined ? {
|
334
|
+
set: props.trade.status
|
335
|
+
} : undefined,
|
336
|
+
symbol: props.trade.symbol !== undefined ? {
|
337
|
+
set: props.trade.symbol
|
338
|
+
} : undefined,
|
339
|
+
entryPrice: props.trade.entryPrice !== undefined ? {
|
340
|
+
set: props.trade.entryPrice
|
341
|
+
} : undefined,
|
342
|
+
exitPrice: props.trade.exitPrice !== undefined ? {
|
343
|
+
set: props.trade.exitPrice
|
344
|
+
} : undefined,
|
345
|
+
entryQty: props.trade.entryQty !== undefined ? {
|
346
|
+
set: props.trade.entryQty
|
347
|
+
} : undefined,
|
348
|
+
exitQty: props.trade.exitQty !== undefined ? {
|
349
|
+
set: props.trade.exitQty
|
350
|
+
} : undefined,
|
351
|
+
entryValue: props.trade.entryValue !== undefined ? {
|
352
|
+
set: props.trade.entryValue
|
353
|
+
} : undefined,
|
354
|
+
exitValue: props.trade.exitValue !== undefined ? {
|
355
|
+
set: props.trade.exitValue
|
356
|
+
} : undefined,
|
357
|
+
entryTime: props.trade.entryTime !== undefined ? {
|
358
|
+
set: props.trade.entryTime
|
359
|
+
} : undefined,
|
360
|
+
exitTime: props.trade.exitTime !== undefined ? {
|
361
|
+
set: props.trade.exitTime
|
362
|
+
} : undefined,
|
363
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? {
|
364
|
+
set: props.trade.pnlAmount
|
365
|
+
} : undefined,
|
366
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? {
|
367
|
+
set: props.trade.pnlPercent
|
368
|
+
} : undefined,
|
369
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? {
|
370
|
+
set: props.trade.durationMinutes
|
371
|
+
} : undefined,
|
372
|
+
marketPhase: props.trade.marketPhase !== undefined ? {
|
373
|
+
set: props.trade.marketPhase
|
374
|
+
} : undefined,
|
375
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? {
|
376
|
+
set: props.trade.marketVolatility
|
377
|
+
} : undefined,
|
378
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? {
|
379
|
+
set: props.trade.thresholdsJson
|
380
|
+
} : undefined,
|
381
|
+
},
|
382
|
+
create: {
|
383
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
384
|
+
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
385
|
+
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
386
|
+
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
387
|
+
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
388
|
+
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
389
|
+
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
390
|
+
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
391
|
+
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
392
|
+
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
393
|
+
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
394
|
+
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
395
|
+
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
396
|
+
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
397
|
+
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
398
|
+
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
399
|
+
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
400
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
401
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
402
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
403
|
+
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
404
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
405
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
406
|
+
},
|
407
|
+
}
|
408
|
+
} : undefined,
|
409
|
+
},
|
410
|
+
};
|
411
|
+
const filteredVariables = removeUndefinedProps(variables);
|
412
|
+
const response = await client.mutate({
|
413
|
+
mutation: UPDATE_ONE_ACTION,
|
414
|
+
variables: filteredVariables,
|
415
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
416
|
+
fetchPolicy: 'no-cache'
|
417
|
+
});
|
418
|
+
if (response.errors && response.errors.length > 0)
|
419
|
+
throw new Error(response.errors[0].message);
|
420
|
+
if (response && response.data && response.data.updateOneAction) {
|
421
|
+
return response.data.updateOneAction;
|
422
|
+
}
|
423
|
+
else {
|
424
|
+
return null;
|
425
|
+
}
|
426
|
+
}
|
427
|
+
catch (error) {
|
428
|
+
lastError = error;
|
429
|
+
// Check if this is a database connection error that we should retry
|
430
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
431
|
+
error.message?.includes('Cannot reach database server') ||
|
432
|
+
error.message?.includes('Connection timed out') ||
|
433
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
434
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
435
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
436
|
+
retryCount++;
|
437
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
438
|
+
console.warn("Database connection error, retrying...");
|
439
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
440
|
+
continue;
|
441
|
+
}
|
442
|
+
// Log the error and rethrow
|
443
|
+
console.error("Database error occurred:", error);
|
444
|
+
throw error;
|
347
445
|
}
|
348
446
|
}
|
349
|
-
|
350
|
-
|
351
|
-
throw error;
|
352
|
-
}
|
447
|
+
// If we exhausted retries, throw the last error
|
448
|
+
throw lastError;
|
353
449
|
},
|
354
450
|
/**
|
355
451
|
* Upsert a single Action record.
|
452
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
356
453
|
* @param props - Properties to update.
|
357
454
|
* @param globalClient - Apollo Client instance.
|
358
455
|
* @returns The updated Action or null.
|
359
456
|
*/
|
360
457
|
async upsert(props, globalClient) {
|
361
|
-
|
362
|
-
|
363
|
-
|
364
|
-
|
365
|
-
|
366
|
-
|
367
|
-
|
368
|
-
|
369
|
-
|
370
|
-
|
371
|
-
|
372
|
-
|
373
|
-
|
374
|
-
|
375
|
-
|
376
|
-
|
377
|
-
|
378
|
-
|
379
|
-
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
status: props.status !== undefined ? props.status : undefined,
|
388
|
-
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
389
|
-
trade: props.trade ?
|
390
|
-
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && Object.keys(props.trade)[0] === 'id'
|
391
|
-
? { connect: {
|
392
|
-
id: props.trade.id
|
393
|
-
}
|
394
|
-
}
|
395
|
-
: { connectOrCreate: {
|
396
|
-
where: {
|
397
|
-
id: props.trade.id !== undefined ? props.trade.id : undefined,
|
398
|
-
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
399
|
-
equals: props.trade.alpacaAccountId
|
400
|
-
} : undefined,
|
401
|
-
symbol: props.trade.symbol !== undefined ? {
|
402
|
-
equals: props.trade.symbol
|
403
|
-
} : undefined,
|
404
|
-
},
|
405
|
-
create: {
|
406
|
-
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
407
|
-
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
408
|
-
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
409
|
-
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
410
|
-
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
411
|
-
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
412
|
-
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
413
|
-
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
414
|
-
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
415
|
-
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
416
|
-
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
417
|
-
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
418
|
-
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
419
|
-
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
420
|
-
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
421
|
-
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
422
|
-
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
423
|
-
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
424
|
-
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
425
|
-
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
426
|
-
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
427
|
-
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
428
|
-
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
429
|
-
},
|
430
|
-
}
|
458
|
+
// Maximum number of retries for database connection issues
|
459
|
+
const MAX_RETRIES = 3;
|
460
|
+
let retryCount = 0;
|
461
|
+
let lastError = null;
|
462
|
+
// Retry loop to handle potential database connection issues
|
463
|
+
while (retryCount < MAX_RETRIES) {
|
464
|
+
try {
|
465
|
+
const [modules, client] = await Promise.all([
|
466
|
+
getApolloModules(),
|
467
|
+
globalClient
|
468
|
+
? Promise.resolve(globalClient)
|
469
|
+
: importedClient
|
470
|
+
]);
|
471
|
+
const { gql, ApolloError } = modules;
|
472
|
+
const UPSERT_ONE_ACTION = gql `
|
473
|
+
mutation upsertOneAction($where: ActionWhereUniqueInput!, $create: ActionCreateInput!, $update: ActionUpdateInput!) {
|
474
|
+
upsertOneAction(where: $where, create: $create, update: $update) {
|
475
|
+
${selectionSet}
|
476
|
+
}
|
477
|
+
}`;
|
478
|
+
const variables = {
|
479
|
+
where: {
|
480
|
+
id: props.id !== undefined ? props.id : undefined,
|
481
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
482
|
+
tradeId: props.tradeId !== undefined ? {
|
483
|
+
equals: props.tradeId
|
431
484
|
} : undefined,
|
432
|
-
|
433
|
-
|
434
|
-
|
435
|
-
|
436
|
-
|
437
|
-
|
438
|
-
|
439
|
-
|
440
|
-
|
441
|
-
|
442
|
-
|
443
|
-
|
444
|
-
|
445
|
-
|
446
|
-
|
447
|
-
|
448
|
-
|
449
|
-
|
450
|
-
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
|
459
|
-
|
460
|
-
|
461
|
-
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
481
|
-
|
482
|
-
} : undefined,
|
483
|
-
|
484
|
-
|
485
|
-
|
486
|
-
|
487
|
-
|
488
|
-
|
489
|
-
|
490
|
-
|
491
|
-
|
492
|
-
|
493
|
-
|
494
|
-
|
495
|
-
|
496
|
-
|
497
|
-
|
498
|
-
|
499
|
-
|
500
|
-
|
501
|
-
|
502
|
-
|
503
|
-
|
504
|
-
|
505
|
-
|
506
|
-
|
507
|
-
|
508
|
-
|
509
|
-
} :
|
510
|
-
|
511
|
-
|
512
|
-
|
513
|
-
|
514
|
-
|
515
|
-
|
516
|
-
|
517
|
-
|
518
|
-
|
519
|
-
|
520
|
-
|
521
|
-
|
522
|
-
|
523
|
-
|
524
|
-
|
525
|
-
|
526
|
-
|
527
|
-
|
528
|
-
|
529
|
-
|
530
|
-
|
531
|
-
|
532
|
-
|
533
|
-
|
534
|
-
|
535
|
-
|
536
|
-
|
537
|
-
|
538
|
-
|
539
|
-
|
540
|
-
|
541
|
-
|
542
|
-
|
543
|
-
|
544
|
-
|
545
|
-
|
546
|
-
|
547
|
-
|
548
|
-
|
549
|
-
|
550
|
-
|
551
|
-
|
552
|
-
|
553
|
-
|
554
|
-
|
555
|
-
|
556
|
-
|
557
|
-
|
558
|
-
|
559
|
-
|
560
|
-
|
561
|
-
|
562
|
-
|
563
|
-
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
485
|
+
},
|
486
|
+
create: {
|
487
|
+
sequence: props.sequence !== undefined ? props.sequence : undefined,
|
488
|
+
type: props.type !== undefined ? props.type : undefined,
|
489
|
+
primary: props.primary !== undefined ? props.primary : undefined,
|
490
|
+
note: props.note !== undefined ? props.note : undefined,
|
491
|
+
status: props.status !== undefined ? props.status : undefined,
|
492
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
493
|
+
trade: props.trade ?
|
494
|
+
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && Object.keys(props.trade)[0] === 'id'
|
495
|
+
? { connect: {
|
496
|
+
id: props.trade.id
|
497
|
+
}
|
498
|
+
}
|
499
|
+
: { connectOrCreate: {
|
500
|
+
where: {
|
501
|
+
id: props.trade.id !== undefined ? props.trade.id : undefined,
|
502
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
503
|
+
equals: props.trade.alpacaAccountId
|
504
|
+
} : undefined,
|
505
|
+
symbol: props.trade.symbol !== undefined ? {
|
506
|
+
equals: props.trade.symbol
|
507
|
+
} : undefined,
|
508
|
+
},
|
509
|
+
create: {
|
510
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
511
|
+
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
512
|
+
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
513
|
+
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
514
|
+
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
515
|
+
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
516
|
+
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
517
|
+
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
518
|
+
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
519
|
+
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
520
|
+
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
521
|
+
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
522
|
+
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
523
|
+
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
524
|
+
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
525
|
+
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
526
|
+
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
527
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
528
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
529
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
530
|
+
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
531
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
532
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
533
|
+
},
|
534
|
+
}
|
535
|
+
} : undefined,
|
536
|
+
},
|
537
|
+
update: {
|
538
|
+
sequence: props.sequence !== undefined ? {
|
539
|
+
set: props.sequence
|
540
|
+
} : undefined,
|
541
|
+
type: props.type !== undefined ? {
|
542
|
+
set: props.type
|
543
|
+
} : undefined,
|
544
|
+
primary: props.primary !== undefined ? {
|
545
|
+
set: props.primary
|
546
|
+
} : undefined,
|
547
|
+
note: props.note !== undefined ? {
|
548
|
+
set: props.note
|
549
|
+
} : undefined,
|
550
|
+
status: props.status !== undefined ? {
|
551
|
+
set: props.status
|
552
|
+
} : undefined,
|
553
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? {
|
554
|
+
set: props.alpacaOrderId
|
555
|
+
} : undefined,
|
556
|
+
trade: props.trade ?
|
557
|
+
typeof props.trade === 'object' && Object.keys(props.trade).length === 1 && (Object.keys(props.trade)[0] === 'id' || Object.keys(props.trade)[0] === 'symbol')
|
558
|
+
? {
|
559
|
+
connect: {
|
560
|
+
id: props.trade.id
|
561
|
+
}
|
562
|
+
} : { upsert: {
|
563
|
+
where: {
|
564
|
+
id: props.trade.id !== undefined ? {
|
565
|
+
equals: props.trade.id
|
566
|
+
} : undefined,
|
567
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
568
|
+
equals: props.trade.alpacaAccountId
|
569
|
+
} : undefined,
|
570
|
+
symbol: props.trade.symbol !== undefined ? {
|
571
|
+
equals: props.trade.symbol
|
572
|
+
} : undefined,
|
573
|
+
},
|
574
|
+
update: {
|
575
|
+
id: props.trade.id !== undefined ? {
|
576
|
+
set: props.trade.id
|
577
|
+
} : undefined,
|
578
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? {
|
579
|
+
set: props.trade.alpacaAccountId
|
580
|
+
} : undefined,
|
581
|
+
signal: props.trade.signal !== undefined ? {
|
582
|
+
set: props.trade.signal
|
583
|
+
} : undefined,
|
584
|
+
strategy: props.trade.strategy !== undefined ? {
|
585
|
+
set: props.trade.strategy
|
586
|
+
} : undefined,
|
587
|
+
analysis: props.trade.analysis !== undefined ? {
|
588
|
+
set: props.trade.analysis
|
589
|
+
} : undefined,
|
590
|
+
summary: props.trade.summary !== undefined ? {
|
591
|
+
set: props.trade.summary
|
592
|
+
} : undefined,
|
593
|
+
confidence: props.trade.confidence !== undefined ? {
|
594
|
+
set: props.trade.confidence
|
595
|
+
} : undefined,
|
596
|
+
timestamp: props.trade.timestamp !== undefined ? {
|
597
|
+
set: props.trade.timestamp
|
598
|
+
} : undefined,
|
599
|
+
status: props.trade.status !== undefined ? {
|
600
|
+
set: props.trade.status
|
601
|
+
} : undefined,
|
602
|
+
symbol: props.trade.symbol !== undefined ? {
|
603
|
+
set: props.trade.symbol
|
604
|
+
} : undefined,
|
605
|
+
entryPrice: props.trade.entryPrice !== undefined ? {
|
606
|
+
set: props.trade.entryPrice
|
607
|
+
} : undefined,
|
608
|
+
exitPrice: props.trade.exitPrice !== undefined ? {
|
609
|
+
set: props.trade.exitPrice
|
610
|
+
} : undefined,
|
611
|
+
entryQty: props.trade.entryQty !== undefined ? {
|
612
|
+
set: props.trade.entryQty
|
613
|
+
} : undefined,
|
614
|
+
exitQty: props.trade.exitQty !== undefined ? {
|
615
|
+
set: props.trade.exitQty
|
616
|
+
} : undefined,
|
617
|
+
entryValue: props.trade.entryValue !== undefined ? {
|
618
|
+
set: props.trade.entryValue
|
619
|
+
} : undefined,
|
620
|
+
exitValue: props.trade.exitValue !== undefined ? {
|
621
|
+
set: props.trade.exitValue
|
622
|
+
} : undefined,
|
623
|
+
entryTime: props.trade.entryTime !== undefined ? {
|
624
|
+
set: props.trade.entryTime
|
625
|
+
} : undefined,
|
626
|
+
exitTime: props.trade.exitTime !== undefined ? {
|
627
|
+
set: props.trade.exitTime
|
628
|
+
} : undefined,
|
629
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? {
|
630
|
+
set: props.trade.pnlAmount
|
631
|
+
} : undefined,
|
632
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? {
|
633
|
+
set: props.trade.pnlPercent
|
634
|
+
} : undefined,
|
635
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? {
|
636
|
+
set: props.trade.durationMinutes
|
637
|
+
} : undefined,
|
638
|
+
marketPhase: props.trade.marketPhase !== undefined ? {
|
639
|
+
set: props.trade.marketPhase
|
640
|
+
} : undefined,
|
641
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? {
|
642
|
+
set: props.trade.marketVolatility
|
643
|
+
} : undefined,
|
644
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? {
|
645
|
+
set: props.trade.thresholdsJson
|
646
|
+
} : undefined,
|
647
|
+
},
|
648
|
+
create: {
|
649
|
+
alpacaAccountId: props.trade.alpacaAccountId !== undefined ? props.trade.alpacaAccountId : undefined,
|
650
|
+
signal: props.trade.signal !== undefined ? props.trade.signal : undefined,
|
651
|
+
strategy: props.trade.strategy !== undefined ? props.trade.strategy : undefined,
|
652
|
+
analysis: props.trade.analysis !== undefined ? props.trade.analysis : undefined,
|
653
|
+
summary: props.trade.summary !== undefined ? props.trade.summary : undefined,
|
654
|
+
confidence: props.trade.confidence !== undefined ? props.trade.confidence : undefined,
|
655
|
+
timestamp: props.trade.timestamp !== undefined ? props.trade.timestamp : undefined,
|
656
|
+
status: props.trade.status !== undefined ? props.trade.status : undefined,
|
657
|
+
symbol: props.trade.symbol !== undefined ? props.trade.symbol : undefined,
|
658
|
+
entryPrice: props.trade.entryPrice !== undefined ? props.trade.entryPrice : undefined,
|
659
|
+
exitPrice: props.trade.exitPrice !== undefined ? props.trade.exitPrice : undefined,
|
660
|
+
entryQty: props.trade.entryQty !== undefined ? props.trade.entryQty : undefined,
|
661
|
+
exitQty: props.trade.exitQty !== undefined ? props.trade.exitQty : undefined,
|
662
|
+
entryValue: props.trade.entryValue !== undefined ? props.trade.entryValue : undefined,
|
663
|
+
exitValue: props.trade.exitValue !== undefined ? props.trade.exitValue : undefined,
|
664
|
+
entryTime: props.trade.entryTime !== undefined ? props.trade.entryTime : undefined,
|
665
|
+
exitTime: props.trade.exitTime !== undefined ? props.trade.exitTime : undefined,
|
666
|
+
pnlAmount: props.trade.pnlAmount !== undefined ? props.trade.pnlAmount : undefined,
|
667
|
+
pnlPercent: props.trade.pnlPercent !== undefined ? props.trade.pnlPercent : undefined,
|
668
|
+
durationMinutes: props.trade.durationMinutes !== undefined ? props.trade.durationMinutes : undefined,
|
669
|
+
marketPhase: props.trade.marketPhase !== undefined ? props.trade.marketPhase : undefined,
|
670
|
+
marketVolatility: props.trade.marketVolatility !== undefined ? props.trade.marketVolatility : undefined,
|
671
|
+
thresholdsJson: props.trade.thresholdsJson !== undefined ? props.trade.thresholdsJson : undefined,
|
672
|
+
},
|
673
|
+
}
|
674
|
+
} : undefined,
|
675
|
+
},
|
676
|
+
};
|
677
|
+
const filteredVariables = removeUndefinedProps(variables);
|
678
|
+
const response = await client.mutate({
|
679
|
+
mutation: UPSERT_ONE_ACTION,
|
680
|
+
variables: filteredVariables,
|
681
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
682
|
+
fetchPolicy: 'no-cache'
|
683
|
+
});
|
684
|
+
if (response.errors && response.errors.length > 0)
|
685
|
+
throw new Error(response.errors[0].message);
|
686
|
+
if (response && response.data && response.data.upsertOneAction) {
|
687
|
+
return response.data.upsertOneAction;
|
688
|
+
}
|
689
|
+
else {
|
690
|
+
return null;
|
691
|
+
}
|
580
692
|
}
|
581
|
-
|
582
|
-
|
693
|
+
catch (error) {
|
694
|
+
lastError = error;
|
695
|
+
// Check if this is a database connection error that we should retry
|
696
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
697
|
+
error.message?.includes('Cannot reach database server') ||
|
698
|
+
error.message?.includes('Connection timed out') ||
|
699
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
700
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
701
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
702
|
+
retryCount++;
|
703
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
704
|
+
console.warn("Database connection error, retrying...");
|
705
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
706
|
+
continue;
|
707
|
+
}
|
708
|
+
// Log the error and rethrow
|
709
|
+
console.error("Database error occurred:", error);
|
710
|
+
throw error;
|
583
711
|
}
|
584
712
|
}
|
585
|
-
|
586
|
-
|
587
|
-
throw error;
|
588
|
-
}
|
713
|
+
// If we exhausted retries, throw the last error
|
714
|
+
throw lastError;
|
589
715
|
},
|
590
716
|
/**
|
591
717
|
* Update multiple Action records.
|
718
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
592
719
|
* @param props - Array of Action objects for the updated records.
|
593
720
|
* @param globalClient - Apollo Client instance.
|
594
721
|
* @returns The count of created records or null.
|
595
722
|
*/
|
596
723
|
async updateMany(props, globalClient) {
|
597
|
-
|
598
|
-
|
599
|
-
|
600
|
-
|
601
|
-
|
602
|
-
|
603
|
-
|
604
|
-
|
605
|
-
|
606
|
-
|
607
|
-
|
608
|
-
|
609
|
-
|
610
|
-
|
611
|
-
|
612
|
-
|
613
|
-
|
614
|
-
|
615
|
-
equals: prop.tradeId
|
616
|
-
} : undefined,
|
617
|
-
},
|
618
|
-
data: {
|
619
|
-
id: prop.id !== undefined ? {
|
620
|
-
set: prop.id
|
621
|
-
} : undefined,
|
622
|
-
sequence: prop.sequence !== undefined ? {
|
623
|
-
set: prop.sequence
|
624
|
-
} : undefined,
|
625
|
-
type: prop.type !== undefined ? {
|
626
|
-
set: prop.type
|
627
|
-
} : undefined,
|
628
|
-
primary: prop.primary !== undefined ? {
|
629
|
-
set: prop.primary
|
630
|
-
} : undefined,
|
631
|
-
note: prop.note !== undefined ? {
|
632
|
-
set: prop.note
|
633
|
-
} : undefined,
|
634
|
-
status: prop.status !== undefined ? {
|
635
|
-
set: prop.status
|
636
|
-
} : undefined,
|
637
|
-
createdAt: prop.createdAt !== undefined ? {
|
638
|
-
set: prop.createdAt
|
639
|
-
} : undefined,
|
640
|
-
updatedAt: prop.updatedAt !== undefined ? {
|
641
|
-
set: prop.updatedAt
|
642
|
-
} : undefined,
|
643
|
-
alpacaOrderId: prop.alpacaOrderId !== undefined ? {
|
644
|
-
set: prop.alpacaOrderId
|
645
|
-
} : undefined,
|
646
|
-
trade: prop.trade ?
|
647
|
-
typeof prop.trade === 'object' && Object.keys(prop.trade).length === 1 && (Object.keys(prop.trade)[0] === 'id' || Object.keys(prop.trade)[0] === 'symbol')
|
648
|
-
? {
|
649
|
-
connect: {
|
650
|
-
id: prop.trade.id
|
651
|
-
}
|
652
|
-
} : { upsert: {
|
653
|
-
where: {
|
654
|
-
id: prop.trade.id !== undefined ? {
|
655
|
-
equals: prop.trade.id
|
656
|
-
} : undefined,
|
657
|
-
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? {
|
658
|
-
equals: prop.trade.alpacaAccountId
|
659
|
-
} : undefined,
|
660
|
-
symbol: prop.trade.symbol !== undefined ? {
|
661
|
-
equals: prop.trade.symbol
|
662
|
-
} : undefined,
|
663
|
-
},
|
664
|
-
update: {
|
665
|
-
id: prop.trade.id !== undefined ? {
|
666
|
-
set: prop.trade.id
|
667
|
-
} : undefined,
|
668
|
-
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? {
|
669
|
-
set: prop.trade.alpacaAccountId
|
670
|
-
} : undefined,
|
671
|
-
signal: prop.trade.signal !== undefined ? {
|
672
|
-
set: prop.trade.signal
|
673
|
-
} : undefined,
|
674
|
-
strategy: prop.trade.strategy !== undefined ? {
|
675
|
-
set: prop.trade.strategy
|
676
|
-
} : undefined,
|
677
|
-
analysis: prop.trade.analysis !== undefined ? {
|
678
|
-
set: prop.trade.analysis
|
679
|
-
} : undefined,
|
680
|
-
summary: prop.trade.summary !== undefined ? {
|
681
|
-
set: prop.trade.summary
|
682
|
-
} : undefined,
|
683
|
-
confidence: prop.trade.confidence !== undefined ? {
|
684
|
-
set: prop.trade.confidence
|
685
|
-
} : undefined,
|
686
|
-
timestamp: prop.trade.timestamp !== undefined ? {
|
687
|
-
set: prop.trade.timestamp
|
688
|
-
} : undefined,
|
689
|
-
status: prop.trade.status !== undefined ? {
|
690
|
-
set: prop.trade.status
|
691
|
-
} : undefined,
|
692
|
-
symbol: prop.trade.symbol !== undefined ? {
|
693
|
-
set: prop.trade.symbol
|
694
|
-
} : undefined,
|
695
|
-
entryPrice: prop.trade.entryPrice !== undefined ? {
|
696
|
-
set: prop.trade.entryPrice
|
697
|
-
} : undefined,
|
698
|
-
exitPrice: prop.trade.exitPrice !== undefined ? {
|
699
|
-
set: prop.trade.exitPrice
|
700
|
-
} : undefined,
|
701
|
-
entryQty: prop.trade.entryQty !== undefined ? {
|
702
|
-
set: prop.trade.entryQty
|
703
|
-
} : undefined,
|
704
|
-
exitQty: prop.trade.exitQty !== undefined ? {
|
705
|
-
set: prop.trade.exitQty
|
706
|
-
} : undefined,
|
707
|
-
entryValue: prop.trade.entryValue !== undefined ? {
|
708
|
-
set: prop.trade.entryValue
|
709
|
-
} : undefined,
|
710
|
-
exitValue: prop.trade.exitValue !== undefined ? {
|
711
|
-
set: prop.trade.exitValue
|
712
|
-
} : undefined,
|
713
|
-
entryTime: prop.trade.entryTime !== undefined ? {
|
714
|
-
set: prop.trade.entryTime
|
715
|
-
} : undefined,
|
716
|
-
exitTime: prop.trade.exitTime !== undefined ? {
|
717
|
-
set: prop.trade.exitTime
|
718
|
-
} : undefined,
|
719
|
-
pnlAmount: prop.trade.pnlAmount !== undefined ? {
|
720
|
-
set: prop.trade.pnlAmount
|
721
|
-
} : undefined,
|
722
|
-
pnlPercent: prop.trade.pnlPercent !== undefined ? {
|
723
|
-
set: prop.trade.pnlPercent
|
724
|
-
} : undefined,
|
725
|
-
durationMinutes: prop.trade.durationMinutes !== undefined ? {
|
726
|
-
set: prop.trade.durationMinutes
|
727
|
-
} : undefined,
|
728
|
-
marketPhase: prop.trade.marketPhase !== undefined ? {
|
729
|
-
set: prop.trade.marketPhase
|
730
|
-
} : undefined,
|
731
|
-
marketVolatility: prop.trade.marketVolatility !== undefined ? {
|
732
|
-
set: prop.trade.marketVolatility
|
733
|
-
} : undefined,
|
734
|
-
thresholdsJson: prop.trade.thresholdsJson !== undefined ? {
|
735
|
-
set: prop.trade.thresholdsJson
|
736
|
-
} : undefined,
|
737
|
-
},
|
738
|
-
create: {
|
739
|
-
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? prop.trade.alpacaAccountId : undefined,
|
740
|
-
signal: prop.trade.signal !== undefined ? prop.trade.signal : undefined,
|
741
|
-
strategy: prop.trade.strategy !== undefined ? prop.trade.strategy : undefined,
|
742
|
-
analysis: prop.trade.analysis !== undefined ? prop.trade.analysis : undefined,
|
743
|
-
summary: prop.trade.summary !== undefined ? prop.trade.summary : undefined,
|
744
|
-
confidence: prop.trade.confidence !== undefined ? prop.trade.confidence : undefined,
|
745
|
-
timestamp: prop.trade.timestamp !== undefined ? prop.trade.timestamp : undefined,
|
746
|
-
status: prop.trade.status !== undefined ? prop.trade.status : undefined,
|
747
|
-
symbol: prop.trade.symbol !== undefined ? prop.trade.symbol : undefined,
|
748
|
-
entryPrice: prop.trade.entryPrice !== undefined ? prop.trade.entryPrice : undefined,
|
749
|
-
exitPrice: prop.trade.exitPrice !== undefined ? prop.trade.exitPrice : undefined,
|
750
|
-
entryQty: prop.trade.entryQty !== undefined ? prop.trade.entryQty : undefined,
|
751
|
-
exitQty: prop.trade.exitQty !== undefined ? prop.trade.exitQty : undefined,
|
752
|
-
entryValue: prop.trade.entryValue !== undefined ? prop.trade.entryValue : undefined,
|
753
|
-
exitValue: prop.trade.exitValue !== undefined ? prop.trade.exitValue : undefined,
|
754
|
-
entryTime: prop.trade.entryTime !== undefined ? prop.trade.entryTime : undefined,
|
755
|
-
exitTime: prop.trade.exitTime !== undefined ? prop.trade.exitTime : undefined,
|
756
|
-
pnlAmount: prop.trade.pnlAmount !== undefined ? prop.trade.pnlAmount : undefined,
|
757
|
-
pnlPercent: prop.trade.pnlPercent !== undefined ? prop.trade.pnlPercent : undefined,
|
758
|
-
durationMinutes: prop.trade.durationMinutes !== undefined ? prop.trade.durationMinutes : undefined,
|
759
|
-
marketPhase: prop.trade.marketPhase !== undefined ? prop.trade.marketPhase : undefined,
|
760
|
-
marketVolatility: prop.trade.marketVolatility !== undefined ? prop.trade.marketVolatility : undefined,
|
761
|
-
thresholdsJson: prop.trade.thresholdsJson !== undefined ? prop.trade.thresholdsJson : undefined,
|
762
|
-
},
|
763
|
-
}
|
764
|
-
} : undefined,
|
765
|
-
},
|
766
|
-
}));
|
767
|
-
const filteredVariables = removeUndefinedProps(variables);
|
768
|
-
try {
|
769
|
-
const response = await client.mutate({ mutation: UPDATE_MANY_ACTION, variables: filteredVariables });
|
770
|
-
if (response.errors && response.errors.length > 0)
|
771
|
-
throw new Error(response.errors[0].message);
|
772
|
-
if (response && response.data && response.data.updateManyAction) {
|
773
|
-
return response.data.updateManyAction;
|
724
|
+
// Maximum number of retries for database connection issues
|
725
|
+
const MAX_RETRIES = 3;
|
726
|
+
let retryCount = 0;
|
727
|
+
let lastError = null;
|
728
|
+
// Retry loop to handle potential database connection issues
|
729
|
+
while (retryCount < MAX_RETRIES) {
|
730
|
+
try {
|
731
|
+
const [modules, client] = await Promise.all([
|
732
|
+
getApolloModules(),
|
733
|
+
globalClient
|
734
|
+
? Promise.resolve(globalClient)
|
735
|
+
: importedClient
|
736
|
+
]);
|
737
|
+
const { gql, ApolloError } = modules;
|
738
|
+
const UPDATE_MANY_ACTION = gql `
|
739
|
+
mutation updateManyAction($data: [ActionCreateManyInput!]!) {
|
740
|
+
updateManyAction(data: $data) {
|
741
|
+
count
|
774
742
|
}
|
775
|
-
|
776
|
-
|
743
|
+
}`;
|
744
|
+
const variables = props.map(prop => ({
|
745
|
+
where: {
|
746
|
+
id: prop.id !== undefined ? prop.id : undefined,
|
747
|
+
alpacaOrderId: prop.alpacaOrderId !== undefined ? prop.alpacaOrderId : undefined,
|
748
|
+
tradeId: prop.tradeId !== undefined ? {
|
749
|
+
equals: prop.tradeId
|
750
|
+
} : undefined,
|
751
|
+
},
|
752
|
+
data: {
|
753
|
+
id: prop.id !== undefined ? {
|
754
|
+
set: prop.id
|
755
|
+
} : undefined,
|
756
|
+
sequence: prop.sequence !== undefined ? {
|
757
|
+
set: prop.sequence
|
758
|
+
} : undefined,
|
759
|
+
type: prop.type !== undefined ? {
|
760
|
+
set: prop.type
|
761
|
+
} : undefined,
|
762
|
+
primary: prop.primary !== undefined ? {
|
763
|
+
set: prop.primary
|
764
|
+
} : undefined,
|
765
|
+
note: prop.note !== undefined ? {
|
766
|
+
set: prop.note
|
767
|
+
} : undefined,
|
768
|
+
status: prop.status !== undefined ? {
|
769
|
+
set: prop.status
|
770
|
+
} : undefined,
|
771
|
+
createdAt: prop.createdAt !== undefined ? {
|
772
|
+
set: prop.createdAt
|
773
|
+
} : undefined,
|
774
|
+
updatedAt: prop.updatedAt !== undefined ? {
|
775
|
+
set: prop.updatedAt
|
776
|
+
} : undefined,
|
777
|
+
alpacaOrderId: prop.alpacaOrderId !== undefined ? {
|
778
|
+
set: prop.alpacaOrderId
|
779
|
+
} : undefined,
|
780
|
+
trade: prop.trade ?
|
781
|
+
typeof prop.trade === 'object' && Object.keys(prop.trade).length === 1 && (Object.keys(prop.trade)[0] === 'id' || Object.keys(prop.trade)[0] === 'symbol')
|
782
|
+
? {
|
783
|
+
connect: {
|
784
|
+
id: prop.trade.id
|
785
|
+
}
|
786
|
+
} : { upsert: {
|
787
|
+
where: {
|
788
|
+
id: prop.trade.id !== undefined ? {
|
789
|
+
equals: prop.trade.id
|
790
|
+
} : undefined,
|
791
|
+
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? {
|
792
|
+
equals: prop.trade.alpacaAccountId
|
793
|
+
} : undefined,
|
794
|
+
symbol: prop.trade.symbol !== undefined ? {
|
795
|
+
equals: prop.trade.symbol
|
796
|
+
} : undefined,
|
797
|
+
},
|
798
|
+
update: {
|
799
|
+
id: prop.trade.id !== undefined ? {
|
800
|
+
set: prop.trade.id
|
801
|
+
} : undefined,
|
802
|
+
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? {
|
803
|
+
set: prop.trade.alpacaAccountId
|
804
|
+
} : undefined,
|
805
|
+
signal: prop.trade.signal !== undefined ? {
|
806
|
+
set: prop.trade.signal
|
807
|
+
} : undefined,
|
808
|
+
strategy: prop.trade.strategy !== undefined ? {
|
809
|
+
set: prop.trade.strategy
|
810
|
+
} : undefined,
|
811
|
+
analysis: prop.trade.analysis !== undefined ? {
|
812
|
+
set: prop.trade.analysis
|
813
|
+
} : undefined,
|
814
|
+
summary: prop.trade.summary !== undefined ? {
|
815
|
+
set: prop.trade.summary
|
816
|
+
} : undefined,
|
817
|
+
confidence: prop.trade.confidence !== undefined ? {
|
818
|
+
set: prop.trade.confidence
|
819
|
+
} : undefined,
|
820
|
+
timestamp: prop.trade.timestamp !== undefined ? {
|
821
|
+
set: prop.trade.timestamp
|
822
|
+
} : undefined,
|
823
|
+
status: prop.trade.status !== undefined ? {
|
824
|
+
set: prop.trade.status
|
825
|
+
} : undefined,
|
826
|
+
symbol: prop.trade.symbol !== undefined ? {
|
827
|
+
set: prop.trade.symbol
|
828
|
+
} : undefined,
|
829
|
+
entryPrice: prop.trade.entryPrice !== undefined ? {
|
830
|
+
set: prop.trade.entryPrice
|
831
|
+
} : undefined,
|
832
|
+
exitPrice: prop.trade.exitPrice !== undefined ? {
|
833
|
+
set: prop.trade.exitPrice
|
834
|
+
} : undefined,
|
835
|
+
entryQty: prop.trade.entryQty !== undefined ? {
|
836
|
+
set: prop.trade.entryQty
|
837
|
+
} : undefined,
|
838
|
+
exitQty: prop.trade.exitQty !== undefined ? {
|
839
|
+
set: prop.trade.exitQty
|
840
|
+
} : undefined,
|
841
|
+
entryValue: prop.trade.entryValue !== undefined ? {
|
842
|
+
set: prop.trade.entryValue
|
843
|
+
} : undefined,
|
844
|
+
exitValue: prop.trade.exitValue !== undefined ? {
|
845
|
+
set: prop.trade.exitValue
|
846
|
+
} : undefined,
|
847
|
+
entryTime: prop.trade.entryTime !== undefined ? {
|
848
|
+
set: prop.trade.entryTime
|
849
|
+
} : undefined,
|
850
|
+
exitTime: prop.trade.exitTime !== undefined ? {
|
851
|
+
set: prop.trade.exitTime
|
852
|
+
} : undefined,
|
853
|
+
pnlAmount: prop.trade.pnlAmount !== undefined ? {
|
854
|
+
set: prop.trade.pnlAmount
|
855
|
+
} : undefined,
|
856
|
+
pnlPercent: prop.trade.pnlPercent !== undefined ? {
|
857
|
+
set: prop.trade.pnlPercent
|
858
|
+
} : undefined,
|
859
|
+
durationMinutes: prop.trade.durationMinutes !== undefined ? {
|
860
|
+
set: prop.trade.durationMinutes
|
861
|
+
} : undefined,
|
862
|
+
marketPhase: prop.trade.marketPhase !== undefined ? {
|
863
|
+
set: prop.trade.marketPhase
|
864
|
+
} : undefined,
|
865
|
+
marketVolatility: prop.trade.marketVolatility !== undefined ? {
|
866
|
+
set: prop.trade.marketVolatility
|
867
|
+
} : undefined,
|
868
|
+
thresholdsJson: prop.trade.thresholdsJson !== undefined ? {
|
869
|
+
set: prop.trade.thresholdsJson
|
870
|
+
} : undefined,
|
871
|
+
},
|
872
|
+
create: {
|
873
|
+
alpacaAccountId: prop.trade.alpacaAccountId !== undefined ? prop.trade.alpacaAccountId : undefined,
|
874
|
+
signal: prop.trade.signal !== undefined ? prop.trade.signal : undefined,
|
875
|
+
strategy: prop.trade.strategy !== undefined ? prop.trade.strategy : undefined,
|
876
|
+
analysis: prop.trade.analysis !== undefined ? prop.trade.analysis : undefined,
|
877
|
+
summary: prop.trade.summary !== undefined ? prop.trade.summary : undefined,
|
878
|
+
confidence: prop.trade.confidence !== undefined ? prop.trade.confidence : undefined,
|
879
|
+
timestamp: prop.trade.timestamp !== undefined ? prop.trade.timestamp : undefined,
|
880
|
+
status: prop.trade.status !== undefined ? prop.trade.status : undefined,
|
881
|
+
symbol: prop.trade.symbol !== undefined ? prop.trade.symbol : undefined,
|
882
|
+
entryPrice: prop.trade.entryPrice !== undefined ? prop.trade.entryPrice : undefined,
|
883
|
+
exitPrice: prop.trade.exitPrice !== undefined ? prop.trade.exitPrice : undefined,
|
884
|
+
entryQty: prop.trade.entryQty !== undefined ? prop.trade.entryQty : undefined,
|
885
|
+
exitQty: prop.trade.exitQty !== undefined ? prop.trade.exitQty : undefined,
|
886
|
+
entryValue: prop.trade.entryValue !== undefined ? prop.trade.entryValue : undefined,
|
887
|
+
exitValue: prop.trade.exitValue !== undefined ? prop.trade.exitValue : undefined,
|
888
|
+
entryTime: prop.trade.entryTime !== undefined ? prop.trade.entryTime : undefined,
|
889
|
+
exitTime: prop.trade.exitTime !== undefined ? prop.trade.exitTime : undefined,
|
890
|
+
pnlAmount: prop.trade.pnlAmount !== undefined ? prop.trade.pnlAmount : undefined,
|
891
|
+
pnlPercent: prop.trade.pnlPercent !== undefined ? prop.trade.pnlPercent : undefined,
|
892
|
+
durationMinutes: prop.trade.durationMinutes !== undefined ? prop.trade.durationMinutes : undefined,
|
893
|
+
marketPhase: prop.trade.marketPhase !== undefined ? prop.trade.marketPhase : undefined,
|
894
|
+
marketVolatility: prop.trade.marketVolatility !== undefined ? prop.trade.marketVolatility : undefined,
|
895
|
+
thresholdsJson: prop.trade.thresholdsJson !== undefined ? prop.trade.thresholdsJson : undefined,
|
896
|
+
},
|
897
|
+
}
|
898
|
+
} : undefined,
|
899
|
+
},
|
900
|
+
}));
|
901
|
+
const filteredVariables = removeUndefinedProps(variables);
|
902
|
+
const response = await client.mutate({
|
903
|
+
mutation: UPDATE_MANY_ACTION,
|
904
|
+
variables: filteredVariables,
|
905
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
906
|
+
fetchPolicy: 'no-cache'
|
907
|
+
});
|
908
|
+
if (response.errors && response.errors.length > 0)
|
909
|
+
throw new Error(response.errors[0].message);
|
910
|
+
if (response && response.data && response.data.updateManyAction) {
|
911
|
+
return response.data.updateManyAction;
|
912
|
+
}
|
913
|
+
else {
|
914
|
+
return null;
|
915
|
+
}
|
916
|
+
}
|
917
|
+
catch (error) {
|
918
|
+
lastError = error;
|
919
|
+
// Check if this is a database connection error that we should retry
|
920
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
921
|
+
error.message?.includes('Cannot reach database server') ||
|
922
|
+
error.message?.includes('Connection timed out') ||
|
923
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
924
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
925
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
926
|
+
retryCount++;
|
927
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
928
|
+
console.warn("Database connection error, retrying...");
|
929
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
930
|
+
continue;
|
931
|
+
}
|
932
|
+
// Log the error and rethrow
|
933
|
+
console.error("Database error occurred:", error);
|
934
|
+
throw error;
|
777
935
|
}
|
778
936
|
}
|
779
|
-
|
780
|
-
|
781
|
-
throw error;
|
782
|
-
}
|
937
|
+
// If we exhausted retries, throw the last error
|
938
|
+
throw lastError;
|
783
939
|
},
|
784
940
|
/**
|
785
941
|
* Delete a single Action record.
|
786
|
-
*
|
942
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
943
|
+
* @param props - Properties to identify the record to delete.
|
787
944
|
* @param globalClient - Apollo Client instance.
|
788
945
|
* @returns The deleted Action or null.
|
789
946
|
*/
|
790
947
|
async delete(props, globalClient) {
|
791
|
-
|
792
|
-
|
793
|
-
|
794
|
-
|
795
|
-
|
796
|
-
|
797
|
-
|
798
|
-
|
799
|
-
|
800
|
-
|
801
|
-
|
802
|
-
|
803
|
-
|
804
|
-
|
805
|
-
|
806
|
-
|
948
|
+
// Maximum number of retries for database connection issues
|
949
|
+
const MAX_RETRIES = 3;
|
950
|
+
let retryCount = 0;
|
951
|
+
let lastError = null;
|
952
|
+
// Retry loop to handle potential database connection issues
|
953
|
+
while (retryCount < MAX_RETRIES) {
|
954
|
+
try {
|
955
|
+
const [modules, client] = await Promise.all([
|
956
|
+
getApolloModules(),
|
957
|
+
globalClient
|
958
|
+
? Promise.resolve(globalClient)
|
959
|
+
: importedClient
|
960
|
+
]);
|
961
|
+
const { gql, ApolloError } = modules;
|
962
|
+
const DELETE_ONE_ACTION = gql `
|
963
|
+
mutation deleteOneAction($where: ActionWhereUniqueInput!) {
|
964
|
+
deleteOneAction(where: $where) {
|
965
|
+
id
|
807
966
|
}
|
808
|
-
|
809
|
-
|
810
|
-
|
811
|
-
|
812
|
-
|
813
|
-
|
814
|
-
|
815
|
-
|
967
|
+
}`;
|
968
|
+
const variables = {
|
969
|
+
where: {
|
970
|
+
id: props.id ? props.id : undefined,
|
971
|
+
}
|
972
|
+
};
|
973
|
+
const filteredVariables = removeUndefinedProps(variables);
|
974
|
+
const response = await client.mutate({
|
975
|
+
mutation: DELETE_ONE_ACTION,
|
976
|
+
variables: filteredVariables,
|
977
|
+
// Don't cache mutations, but ensure we're using the freshest context
|
978
|
+
fetchPolicy: 'no-cache'
|
979
|
+
});
|
980
|
+
if (response.errors && response.errors.length > 0)
|
981
|
+
throw new Error(response.errors[0].message);
|
982
|
+
if (response && response.data && response.data.deleteOneAction) {
|
983
|
+
return response.data.deleteOneAction;
|
984
|
+
}
|
985
|
+
else {
|
986
|
+
return null;
|
987
|
+
}
|
816
988
|
}
|
817
|
-
|
818
|
-
|
989
|
+
catch (error) {
|
990
|
+
lastError = error;
|
991
|
+
// Check if this is a database connection error that we should retry
|
992
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
993
|
+
error.message?.includes('Cannot reach database server') ||
|
994
|
+
error.message?.includes('Connection timed out') ||
|
995
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
996
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
997
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
998
|
+
retryCount++;
|
999
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
1000
|
+
console.warn("Database connection error, retrying...");
|
1001
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
1002
|
+
continue;
|
1003
|
+
}
|
1004
|
+
// Log the error and rethrow
|
1005
|
+
console.error("Database error occurred:", error);
|
1006
|
+
throw error;
|
819
1007
|
}
|
820
1008
|
}
|
821
|
-
|
822
|
-
|
823
|
-
throw error;
|
824
|
-
}
|
1009
|
+
// If we exhausted retries, throw the last error
|
1010
|
+
throw lastError;
|
825
1011
|
},
|
826
1012
|
/**
|
827
1013
|
* Retrieve a single Action record by ID.
|
828
|
-
*
|
1014
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
1015
|
+
* @param props - Properties to identify the record.
|
829
1016
|
* @param globalClient - Apollo Client instance.
|
1017
|
+
* @param whereInput - Optional custom where input.
|
830
1018
|
* @returns The retrieved Action or null.
|
831
1019
|
*/
|
832
1020
|
async get(props, globalClient, whereInput) {
|
833
|
-
|
834
|
-
|
835
|
-
|
836
|
-
|
837
|
-
|
838
|
-
|
839
|
-
|
840
|
-
|
841
|
-
|
842
|
-
|
843
|
-
|
844
|
-
|
845
|
-
|
846
|
-
|
847
|
-
|
848
|
-
|
849
|
-
|
850
|
-
|
851
|
-
|
852
|
-
|
853
|
-
|
854
|
-
|
855
|
-
|
856
|
-
|
857
|
-
|
858
|
-
|
859
|
-
|
860
|
-
|
861
|
-
|
862
|
-
|
863
|
-
|
864
|
-
|
1021
|
+
// Maximum number of retries for database connection issues
|
1022
|
+
const MAX_RETRIES = 3;
|
1023
|
+
let retryCount = 0;
|
1024
|
+
let lastError = null;
|
1025
|
+
// Retry loop to handle potential database connection issues
|
1026
|
+
while (retryCount < MAX_RETRIES) {
|
1027
|
+
try {
|
1028
|
+
const [modules, client] = await Promise.all([
|
1029
|
+
getApolloModules(),
|
1030
|
+
globalClient
|
1031
|
+
? Promise.resolve(globalClient)
|
1032
|
+
: importedClient
|
1033
|
+
]);
|
1034
|
+
const { gql, ApolloError } = modules;
|
1035
|
+
const GET_ACTION = gql `
|
1036
|
+
query getAction($where: ActionWhereUniqueInput!) {
|
1037
|
+
getAction(where: $where) {
|
1038
|
+
${selectionSet}
|
1039
|
+
}
|
1040
|
+
}`;
|
1041
|
+
const variables = {
|
1042
|
+
where: whereInput ? whereInput : {
|
1043
|
+
id: props.id !== undefined ? props.id : undefined,
|
1044
|
+
alpacaOrderId: props.alpacaOrderId !== undefined ? props.alpacaOrderId : undefined,
|
1045
|
+
tradeId: props.tradeId !== undefined ? {
|
1046
|
+
equals: props.tradeId
|
1047
|
+
} : undefined,
|
1048
|
+
},
|
1049
|
+
};
|
1050
|
+
const filteredVariables = removeUndefinedProps(variables);
|
1051
|
+
const response = await client.query({
|
1052
|
+
query: GET_ACTION,
|
1053
|
+
variables: filteredVariables,
|
1054
|
+
fetchPolicy: 'network-only', // Force network request to avoid stale cache
|
1055
|
+
});
|
1056
|
+
if (response.errors && response.errors.length > 0)
|
1057
|
+
throw new Error(response.errors[0].message);
|
1058
|
+
return response.data?.getAction ?? null;
|
865
1059
|
}
|
866
|
-
|
867
|
-
|
1060
|
+
catch (error) {
|
1061
|
+
lastError = error;
|
1062
|
+
// Check if this is a "No record found" error - this is an expected condition, not a failure
|
1063
|
+
if (error.message === 'No Action found') {
|
1064
|
+
return null;
|
1065
|
+
}
|
1066
|
+
// Check if this is a database connection error that we should retry
|
1067
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
1068
|
+
error.message?.includes('Cannot reach database server') ||
|
1069
|
+
error.message?.includes('Connection timed out') ||
|
1070
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
1071
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
1072
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
1073
|
+
retryCount++;
|
1074
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
1075
|
+
console.warn("Database connection error, retrying...");
|
1076
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
1077
|
+
continue;
|
1078
|
+
}
|
1079
|
+
// Log the error and rethrow
|
1080
|
+
console.error("Database error occurred:", error);
|
868
1081
|
throw error;
|
869
1082
|
}
|
870
1083
|
}
|
1084
|
+
// If we exhausted retries, throw the last error
|
1085
|
+
throw lastError;
|
871
1086
|
},
|
872
1087
|
/**
|
873
1088
|
* Retrieve all Actions records.
|
1089
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
874
1090
|
* @param globalClient - Apollo Client instance.
|
875
1091
|
* @returns An array of Action records or null.
|
876
1092
|
*/
|
877
1093
|
async getAll(globalClient) {
|
878
|
-
|
879
|
-
|
880
|
-
|
881
|
-
|
882
|
-
|
883
|
-
|
884
|
-
|
885
|
-
|
886
|
-
|
887
|
-
|
888
|
-
|
889
|
-
|
890
|
-
|
891
|
-
|
892
|
-
|
893
|
-
|
894
|
-
|
895
|
-
|
896
|
-
}
|
897
|
-
catch (error) {
|
898
|
-
if (error instanceof ApolloError && error.message === 'No Action found') {
|
899
|
-
return null;
|
1094
|
+
// Maximum number of retries for database connection issues
|
1095
|
+
const MAX_RETRIES = 3;
|
1096
|
+
let retryCount = 0;
|
1097
|
+
let lastError = null;
|
1098
|
+
// Retry loop to handle potential database connection issues
|
1099
|
+
while (retryCount < MAX_RETRIES) {
|
1100
|
+
try {
|
1101
|
+
const [modules, client] = await Promise.all([
|
1102
|
+
getApolloModules(),
|
1103
|
+
globalClient
|
1104
|
+
? Promise.resolve(globalClient)
|
1105
|
+
: importedClient
|
1106
|
+
]);
|
1107
|
+
const { gql, ApolloError } = modules;
|
1108
|
+
const GET_ALL_ACTION = gql `
|
1109
|
+
query getAllAction {
|
1110
|
+
actions {
|
1111
|
+
${selectionSet}
|
900
1112
|
}
|
901
|
-
|
902
|
-
|
1113
|
+
}`;
|
1114
|
+
const response = await client.query({
|
1115
|
+
query: GET_ALL_ACTION,
|
1116
|
+
fetchPolicy: 'network-only', // Force network request to avoid stale cache
|
1117
|
+
});
|
1118
|
+
if (response.errors && response.errors.length > 0)
|
1119
|
+
throw new Error(response.errors[0].message);
|
1120
|
+
return response.data?.actions ?? null;
|
1121
|
+
}
|
1122
|
+
catch (error) {
|
1123
|
+
lastError = error;
|
1124
|
+
// Check if this is a "No record found" error - this is an expected condition, not a failure
|
1125
|
+
if (error.message === 'No Action found') {
|
1126
|
+
return null;
|
1127
|
+
}
|
1128
|
+
// Check if this is a database connection error that we should retry
|
1129
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
1130
|
+
error.message?.includes('Cannot reach database server') ||
|
1131
|
+
error.message?.includes('Connection timed out') ||
|
1132
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
1133
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
1134
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
1135
|
+
retryCount++;
|
1136
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
1137
|
+
console.warn("Database connection error, retrying...");
|
1138
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
1139
|
+
continue;
|
1140
|
+
}
|
1141
|
+
// Log the error and rethrow
|
1142
|
+
console.error("Database error occurred:", error);
|
903
1143
|
throw error;
|
904
1144
|
}
|
905
1145
|
}
|
1146
|
+
// If we exhausted retries, throw the last error
|
1147
|
+
throw lastError;
|
906
1148
|
},
|
907
1149
|
/**
|
908
1150
|
* Find multiple Action records based on conditions.
|
1151
|
+
* Enhanced with connection resilience against Prisma connection errors.
|
909
1152
|
* @param props - Conditions to find records.
|
910
1153
|
* @param globalClient - Apollo Client instance.
|
1154
|
+
* @param whereInput - Optional custom where input.
|
911
1155
|
* @returns An array of found Action records or null.
|
912
1156
|
*/
|
913
1157
|
async findMany(props, globalClient, whereInput) {
|
914
|
-
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
|
919
|
-
|
920
|
-
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
|
926
|
-
|
927
|
-
|
928
|
-
|
929
|
-
|
930
|
-
|
931
|
-
|
932
|
-
tradeId: props.tradeId !== undefined ? {
|
933
|
-
equals: props.tradeId
|
934
|
-
} : undefined,
|
935
|
-
},
|
936
|
-
};
|
937
|
-
const filteredVariables = removeUndefinedProps(variables);
|
938
|
-
try {
|
939
|
-
const response = await client.query({ query: FIND_MANY_ACTION, variables: filteredVariables });
|
940
|
-
if (response.errors && response.errors.length > 0)
|
941
|
-
throw new Error(response.errors[0].message);
|
942
|
-
if (response && response.data && response.data.actions) {
|
943
|
-
return response.data.actions;
|
1158
|
+
// Maximum number of retries for database connection issues
|
1159
|
+
const MAX_RETRIES = 3;
|
1160
|
+
let retryCount = 0;
|
1161
|
+
let lastError = null;
|
1162
|
+
// Retry loop to handle potential database connection issues
|
1163
|
+
while (retryCount < MAX_RETRIES) {
|
1164
|
+
try {
|
1165
|
+
const [modules, client] = await Promise.all([
|
1166
|
+
getApolloModules(),
|
1167
|
+
globalClient
|
1168
|
+
? Promise.resolve(globalClient)
|
1169
|
+
: importedClient
|
1170
|
+
]);
|
1171
|
+
const { gql, ApolloError } = modules;
|
1172
|
+
const FIND_MANY_ACTION = gql `
|
1173
|
+
query findManyAction($where: ActionWhereInput!) {
|
1174
|
+
actions(where: $where) {
|
1175
|
+
${selectionSet}
|
944
1176
|
}
|
945
|
-
|
946
|
-
|
947
|
-
|
948
|
-
|
949
|
-
|
950
|
-
|
951
|
-
|
1177
|
+
}`;
|
1178
|
+
const variables = {
|
1179
|
+
where: whereInput ? whereInput : {
|
1180
|
+
id: props.id !== undefined ? {
|
1181
|
+
equals: props.id
|
1182
|
+
} : undefined,
|
1183
|
+
tradeId: props.tradeId !== undefined ? {
|
1184
|
+
equals: props.tradeId
|
1185
|
+
} : undefined,
|
1186
|
+
},
|
1187
|
+
};
|
1188
|
+
const filteredVariables = removeUndefinedProps(variables);
|
1189
|
+
const response = await client.query({
|
1190
|
+
query: FIND_MANY_ACTION,
|
1191
|
+
variables: filteredVariables,
|
1192
|
+
fetchPolicy: 'network-only', // Force network request to avoid stale cache
|
1193
|
+
});
|
1194
|
+
if (response.errors && response.errors.length > 0)
|
1195
|
+
throw new Error(response.errors[0].message);
|
1196
|
+
if (response && response.data && response.data.actions) {
|
1197
|
+
return response.data.actions;
|
1198
|
+
}
|
1199
|
+
else {
|
1200
|
+
return [];
|
1201
|
+
}
|
952
1202
|
}
|
953
|
-
|
954
|
-
|
1203
|
+
catch (error) {
|
1204
|
+
lastError = error;
|
1205
|
+
// Check if this is a "No record found" error - this is an expected condition, not a failure
|
1206
|
+
if (error.message === 'No Action found') {
|
1207
|
+
return null;
|
1208
|
+
}
|
1209
|
+
// Check if this is a database connection error that we should retry
|
1210
|
+
const isConnectionError = error.message?.includes('Server has closed the connection') ||
|
1211
|
+
error.message?.includes('Cannot reach database server') ||
|
1212
|
+
error.message?.includes('Connection timed out') ||
|
1213
|
+
error.message?.includes('Accelerate') || // Prisma Accelerate proxy errors
|
1214
|
+
(error.networkError && error.networkError.message?.includes('Failed to fetch'));
|
1215
|
+
if (isConnectionError && retryCount < MAX_RETRIES - 1) {
|
1216
|
+
retryCount++;
|
1217
|
+
const delay = Math.pow(2, retryCount) * 100; // Exponential backoff: 200ms, 400ms, 800ms
|
1218
|
+
console.warn("Database connection error, retrying...");
|
1219
|
+
await new Promise(resolve => setTimeout(resolve, delay));
|
1220
|
+
continue;
|
1221
|
+
}
|
1222
|
+
// Log the error and rethrow
|
1223
|
+
console.error("Database error occurred:", error);
|
955
1224
|
throw error;
|
956
1225
|
}
|
957
1226
|
}
|
1227
|
+
// If we exhausted retries, throw the last error
|
1228
|
+
throw lastError;
|
958
1229
|
}
|
959
1230
|
};
|
960
1231
|
//# sourceMappingURL=Action.js.map
|