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