@aj-archipelago/cortex 1.1.2 → 1.1.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/redisSubscription.js +43 -27
- package/lib/request.js +0 -1
- package/package.json +1 -1
- package/server/pathwayResolver.js +3 -3
- package/server/rest.js +4 -5
- package/server/subscriptions.js +2 -0
package/lib/redisSubscription.js
CHANGED
|
@@ -46,7 +46,7 @@ if (connectionString) {
|
|
|
46
46
|
channels.forEach(channel => {
|
|
47
47
|
subscriptionClient.subscribe(channel, (error) => {
|
|
48
48
|
if (error) {
|
|
49
|
-
logger.error(`Error subscribing to
|
|
49
|
+
logger.error(`Error subscribing to Redis channel ${channel}: ${error}`);
|
|
50
50
|
} else {
|
|
51
51
|
logger.info(`Subscribed to channel ${channel}`);
|
|
52
52
|
}
|
|
@@ -55,26 +55,22 @@ if (connectionString) {
|
|
|
55
55
|
});
|
|
56
56
|
|
|
57
57
|
subscriptionClient.on('message', (channel, message) => {
|
|
58
|
-
logger.debug(`Received message from ${channel}: ${message}`);
|
|
58
|
+
logger.debug(`Received message from Redis channel ${channel}: ${message}`);
|
|
59
59
|
|
|
60
|
-
let decryptedMessage;
|
|
61
|
-
|
|
62
|
-
if (channel === requestProgressChannel && redisEncryptionKey) {
|
|
63
|
-
try {
|
|
64
|
-
decryptedMessage = decrypt(message, redisEncryptionKey);
|
|
65
|
-
} catch (error) {
|
|
66
|
-
logger.error(`Error decrypting message: ${error}`);
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
decryptedMessage = decryptedMessage || message;
|
|
71
|
-
|
|
72
60
|
let parsedMessage;
|
|
73
61
|
|
|
74
62
|
try {
|
|
75
|
-
parsedMessage = JSON.parse(
|
|
63
|
+
parsedMessage = JSON.parse(message);
|
|
76
64
|
} catch (error) {
|
|
77
|
-
|
|
65
|
+
if (channel === requestProgressChannel && redisEncryptionKey) {
|
|
66
|
+
try {
|
|
67
|
+
parsedMessage = JSON.parse(decrypt(message, redisEncryptionKey));
|
|
68
|
+
} catch (error) {
|
|
69
|
+
logger.error(`Error parsing or decrypting message: ${error}`);
|
|
70
|
+
}
|
|
71
|
+
} else {
|
|
72
|
+
logger.error(`Error parsing message: ${error}`);
|
|
73
|
+
}
|
|
78
74
|
}
|
|
79
75
|
|
|
80
76
|
switch(channel) {
|
|
@@ -95,8 +91,8 @@ if (connectionString) {
|
|
|
95
91
|
logger.info(`Using pubsub publish for channel ${requestProgressChannel}`);
|
|
96
92
|
}
|
|
97
93
|
|
|
98
|
-
async function publishRequestProgress(data
|
|
99
|
-
if (publisherClient && useRedis) {
|
|
94
|
+
async function publishRequestProgress(data) {
|
|
95
|
+
if (publisherClient && requestState?.[data?.requestId]?.useRedis) {
|
|
100
96
|
try {
|
|
101
97
|
let message = JSON.stringify(data);
|
|
102
98
|
if (redisEncryptionKey) {
|
|
@@ -106,10 +102,10 @@ async function publishRequestProgress(data, useRedis = true) {
|
|
|
106
102
|
logger.error(`Error encrypting message: ${error}`);
|
|
107
103
|
}
|
|
108
104
|
}
|
|
109
|
-
logger.debug(`Publishing
|
|
105
|
+
logger.debug(`Publishing request progress ${message} to Redis channel ${requestProgressChannel}`);
|
|
110
106
|
await publisherClient.publish(requestProgressChannel, message);
|
|
111
107
|
} catch (error) {
|
|
112
|
-
logger.error(`Error publishing
|
|
108
|
+
logger.error(`Error publishing request progress to Redis: ${error}`);
|
|
113
109
|
}
|
|
114
110
|
} else {
|
|
115
111
|
pubsubHandleMessage(data);
|
|
@@ -119,11 +115,30 @@ async function publishRequestProgress(data, useRedis = true) {
|
|
|
119
115
|
async function publishRequestProgressSubscription(data) {
|
|
120
116
|
if (publisherClient) {
|
|
121
117
|
try {
|
|
122
|
-
const
|
|
123
|
-
|
|
124
|
-
|
|
118
|
+
const requestIds = data;
|
|
119
|
+
const idsToForward = [];
|
|
120
|
+
// If any of these requests belong to this instance, we can just start and handle them locally
|
|
121
|
+
for (const requestId of requestIds) {
|
|
122
|
+
if (requestState[requestId]) {
|
|
123
|
+
if (!requestState[requestId].started) {
|
|
124
|
+
requestState[requestId].started = true;
|
|
125
|
+
requestState[requestId].useRedis = false;
|
|
126
|
+
logger.info(`Starting local execution for registered async request: ${requestId}`);
|
|
127
|
+
const { resolver, args } = requestState[requestId];
|
|
128
|
+
resolver(args, false);
|
|
129
|
+
}
|
|
130
|
+
} else {
|
|
131
|
+
idsToForward.push(requestId);
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
if (idsToForward.length > 0) {
|
|
136
|
+
const message = JSON.stringify(idsToForward);
|
|
137
|
+
logger.debug(`Sending subscription request(s) to channel ${requestProgressSubscriptionsChannel} for remote execution: ${message}`);
|
|
138
|
+
await publisherClient.publish(requestProgressSubscriptionsChannel, message);
|
|
139
|
+
}
|
|
125
140
|
} catch (error) {
|
|
126
|
-
logger.error(`Error
|
|
141
|
+
logger.error(`Error handling subscription: ${error}`);
|
|
127
142
|
}
|
|
128
143
|
} else {
|
|
129
144
|
handleSubscription(data);
|
|
@@ -132,11 +147,11 @@ async function publishRequestProgressSubscription(data) {
|
|
|
132
147
|
|
|
133
148
|
function pubsubHandleMessage(data){
|
|
134
149
|
const message = JSON.stringify(data);
|
|
135
|
-
logger.debug(`Publishing
|
|
150
|
+
logger.debug(`Publishing request progress to local subscribers: ${message}`);
|
|
136
151
|
try {
|
|
137
152
|
pubsub.publish('REQUEST_PROGRESS', { requestProgress: data });
|
|
138
153
|
} catch (error) {
|
|
139
|
-
logger.error(`Error publishing
|
|
154
|
+
logger.error(`Error publishing request progress to local subscribers: ${error}`);
|
|
140
155
|
}
|
|
141
156
|
}
|
|
142
157
|
|
|
@@ -145,7 +160,8 @@ function handleSubscription(data){
|
|
|
145
160
|
for (const requestId of requestIds) {
|
|
146
161
|
if (requestState[requestId] && !requestState[requestId].started) {
|
|
147
162
|
requestState[requestId].started = true;
|
|
148
|
-
|
|
163
|
+
requestState[requestId].useRedis = true;
|
|
164
|
+
logger.info(`Starting execution for registered async request: ${requestId}`);
|
|
149
165
|
const { resolver, args } = requestState[requestId];
|
|
150
166
|
resolver(args);
|
|
151
167
|
}
|
package/lib/request.js
CHANGED
|
@@ -46,7 +46,6 @@ const buildLimiters = (config) => {
|
|
|
46
46
|
if (connection) {
|
|
47
47
|
limiterOptions.id = `${cortexId}-${name}-limiter`; // Unique id for each limiter
|
|
48
48
|
limiterOptions.connection = connection; // Shared Redis connection
|
|
49
|
-
limiterOptions.clearDatastore = true; // Clear Redis datastore on startup
|
|
50
49
|
}
|
|
51
50
|
|
|
52
51
|
limiters[name] = new Bottleneck(limiterOptions);
|
package/package.json
CHANGED
|
@@ -70,7 +70,7 @@ class PathwayResolver {
|
|
|
70
70
|
// the graphql subscription to send progress updates to the client. Most of
|
|
71
71
|
// the time the client will be an external client, but it could also be the
|
|
72
72
|
// Cortex REST api code.
|
|
73
|
-
async asyncResolve(args
|
|
73
|
+
async asyncResolve(args) {
|
|
74
74
|
const MAX_RETRY_COUNT = 3;
|
|
75
75
|
let attempt = 0;
|
|
76
76
|
let streamErrorOccurred = false;
|
|
@@ -88,7 +88,7 @@ class PathwayResolver {
|
|
|
88
88
|
requestId: this.requestId,
|
|
89
89
|
progress: completedCount / totalCount,
|
|
90
90
|
data: JSON.stringify(responseData),
|
|
91
|
-
}
|
|
91
|
+
});
|
|
92
92
|
}
|
|
93
93
|
} else {
|
|
94
94
|
try {
|
|
@@ -140,7 +140,7 @@ class PathwayResolver {
|
|
|
140
140
|
|
|
141
141
|
try {
|
|
142
142
|
//logger.info(`Publishing stream message to requestId ${this.requestId}: ${message}`);
|
|
143
|
-
publishRequestProgress(requestProgress
|
|
143
|
+
publishRequestProgress(requestProgress);
|
|
144
144
|
} catch (error) {
|
|
145
145
|
logger.error(`Could not publish the stream message: "${messageBuffer}", ${error}`);
|
|
146
146
|
}
|
package/server/rest.js
CHANGED
|
@@ -167,11 +167,10 @@ const processIncomingStream = (requestId, res, jsonResponse) => {
|
|
|
167
167
|
// Fire the resolver for the async requestProgress
|
|
168
168
|
logger.info(`Rest Endpoint starting async requestProgress, requestId: ${requestId}`);
|
|
169
169
|
const { resolver, args } = requestState[requestId];
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
resolver(args, false);
|
|
170
|
+
requestState[requestId].useRedis = false;
|
|
171
|
+
requestState[requestId].started = true;
|
|
172
|
+
|
|
173
|
+
resolver(args);
|
|
175
174
|
|
|
176
175
|
return subscription;
|
|
177
176
|
|
package/server/subscriptions.js
CHANGED
|
@@ -1,11 +1,13 @@
|
|
|
1
1
|
import pubsub from './pubsub.js';
|
|
2
2
|
import { withFilter } from 'graphql-subscriptions';
|
|
3
3
|
import { publishRequestProgressSubscription } from '../lib/redisSubscription.js';
|
|
4
|
+
import logger from '../lib/logger.js';
|
|
4
5
|
|
|
5
6
|
const subscriptions = {
|
|
6
7
|
requestProgress: {
|
|
7
8
|
subscribe: withFilter(
|
|
8
9
|
(_, args, __, _info) => {
|
|
10
|
+
logger.debug(`Client requested subscription for request ids: ${args.requestIds}`);
|
|
9
11
|
publishRequestProgressSubscription(args.requestIds);
|
|
10
12
|
return pubsub.asyncIterator(['REQUEST_PROGRESS'])
|
|
11
13
|
},
|