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