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