@axiom-lattice/gateway 2.1.5 → 2.1.7

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.
@@ -1,11 +1,19 @@
1
- // Queue service adapter that supports both Redis and memory implementations
2
- // Defaults to memory implementation
1
+ // Queue service adapter that uses QueueLatticeManager from core package
2
+ // Provides backward-compatible API for gateway services
3
3
 
4
- import * as memoryQueueService from "./queue_service_memory";
5
- import * as redisQueueService from "./queue_service_redis";
4
+ import {
5
+ queueLatticeManager,
6
+ registerQueueLattice,
7
+ getQueueLattice,
8
+ } from "@axiom-lattice/core";
9
+ import { QueueType, QueueConfig, QueueClient } from "@axiom-lattice/protocols";
10
+ import { RedisQueueClient } from "@axiom-lattice/queue-redis";
6
11
 
7
12
  export type QueueServiceType = "memory" | "redis";
8
13
 
14
+ // Default queue key
15
+ const DEFAULT_QUEUE_KEY = "default";
16
+
9
17
  // Global configuration for queue service type
10
18
  // Can be set via environment variable QUEUE_SERVICE_TYPE or via LatticeGateway configuration
11
19
  let queueServiceType: QueueServiceType =
@@ -13,11 +21,45 @@ let queueServiceType: QueueServiceType =
13
21
 
14
22
  /**
15
23
  * Configure the queue service type
24
+ * This will register or update the default queue service
16
25
  * @param type - "memory" or "redis"
17
26
  */
18
27
  export const setQueueServiceType = (type: QueueServiceType): void => {
19
28
  queueServiceType = type;
20
29
  console.log(`Queue service type set to: ${type}`);
30
+
31
+ // Register or update the queue service
32
+ const queueName = process.env.QUEUE_NAME || "tasks";
33
+ const config: QueueConfig = {
34
+ name: "Default Queue Service",
35
+ description: `Default ${type} queue service`,
36
+ type: type === "redis" ? QueueType.REDIS : QueueType.MEMORY,
37
+ queueName,
38
+ options:
39
+ type === "redis"
40
+ ? {
41
+ redisUrl: process.env.REDIS_URL,
42
+ redisPassword: process.env.REDIS_PASSWORD,
43
+ }
44
+ : undefined,
45
+ };
46
+
47
+ // Remove existing queue if it exists
48
+ if (queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
49
+ queueLatticeManager.removeLattice(DEFAULT_QUEUE_KEY);
50
+ }
51
+
52
+ // Create client for Redis type
53
+ let client: QueueClient | undefined;
54
+ if (type === "redis") {
55
+ client = new RedisQueueClient(queueName, {
56
+ redisUrl: process.env.REDIS_URL,
57
+ redisPassword: process.env.REDIS_PASSWORD,
58
+ });
59
+ }
60
+
61
+ // Register the new queue service
62
+ registerQueueLattice(DEFAULT_QUEUE_KEY, config, client);
21
63
  };
22
64
 
23
65
  /**
@@ -27,17 +69,35 @@ export const getQueueServiceType = (): QueueServiceType => {
27
69
  return queueServiceType;
28
70
  };
29
71
 
30
- // Select the appropriate implementation based on configuration
72
+ /**
73
+ * Get the default queue service
74
+ * If not registered, register it with the current configuration
75
+ */
31
76
  const getQueueService = () => {
32
- return queueServiceType === "redis" ? redisQueueService : memoryQueueService;
77
+ // Check if queue is already registered
78
+ if (!queueLatticeManager.hasLattice(DEFAULT_QUEUE_KEY)) {
79
+ // Auto-register with current configuration
80
+ setQueueServiceType(queueServiceType);
81
+ }
82
+
83
+ return getQueueLattice(DEFAULT_QUEUE_KEY);
33
84
  };
34
85
 
86
+ /**
87
+ * Push agent task to queue
88
+ * @param agentTask - Agent task to push
89
+ */
35
90
  export const pushAgentTaskToQueue = async (agentTask: any) => {
36
- const service = getQueueService();
37
- return service.pushAgentTaskToQueue(agentTask);
91
+ const queue = getQueueService();
92
+ const result = await queue.push(agentTask);
93
+ return result;
38
94
  };
39
95
 
96
+ /**
97
+ * Pop agent task from queue
98
+ */
40
99
  export const popAgentTaskFromQueue = async () => {
41
- const service = getQueueService();
42
- return service.popAgentTaskFromQueue();
100
+ const queue = getQueueService();
101
+ const result = await queue.pop();
102
+ return result;
43
103
  };
@@ -1,46 +0,0 @@
1
- import { AGENT_TASK_EVENT } from "./agent_task_types";
2
- import eventBus from "./event_bus";
3
-
4
- export class AgentManager {
5
- private static instance: AgentManager;
6
- private constructor() {}
7
- private agents: { name: string; agent: any }[] = [];
8
- public static getInstance(): AgentManager {
9
- if (!AgentManager.instance) {
10
- AgentManager.instance = new AgentManager();
11
- }
12
- return AgentManager.instance;
13
- }
14
- callAgentInQueue(queue: {
15
- assistant_id: string;
16
- input?: any;
17
- thread_id: string;
18
- command?: any;
19
- "x-tenant-id"?: string;
20
- }) {
21
- return new Promise((resolve, reject) => {
22
- //const callback_event = `${queue.assistant_id}::${queue.thread_id}`;
23
- // eventBus.subscribeOnce(callback_event, (data) => {
24
- // if (data.success) {
25
- // console.log("AgentManager callAgentInQueue success", data);
26
- // resolve(data.result);
27
- // } else {
28
- // console.log("AgentManager callAgentInQueue error", data);
29
- // reject(data.error);
30
- // }
31
- // });
32
- try {
33
- eventBus.publish(
34
- AGENT_TASK_EVENT,
35
- {
36
- ...queue,
37
- },
38
- true
39
- );
40
- resolve(true);
41
- } catch (error) {
42
- reject(error);
43
- }
44
- });
45
- }
46
- }
@@ -1,2 +0,0 @@
1
- // 任务事件名称
2
- export const AGENT_TASK_EVENT = "agent:execute";
@@ -1,62 +0,0 @@
1
- import { EventEmitter } from "events";
2
- import { pushAgentTaskToQueue } from "./queue_service";
3
-
4
- /**
5
- * 事件总线服务
6
- * 用于系统内部组件间的事件发布与订阅
7
- */
8
- class EventBus {
9
- private emitter: EventEmitter;
10
-
11
- constructor() {
12
- this.emitter = new EventEmitter();
13
- // 设置最大监听器数量,避免内存泄漏警告
14
- this.emitter.setMaxListeners(100);
15
- }
16
-
17
- /**
18
- * 发布事件
19
- * @param eventName 事件名称
20
- * @param data 事件数据
21
- */
22
- publish(eventName: string, data: any, useQueue: boolean = false): void {
23
- //console.log(`发布事件: ${eventName}`, data);
24
- if (useQueue) {
25
- pushAgentTaskToQueue(data);
26
- } else {
27
- this.emitter.emit(eventName, data);
28
- }
29
- }
30
-
31
- /**
32
- * 订阅事件
33
- * @param eventName 事件名称
34
- * @param callback 回调函数
35
- */
36
- subscribe(eventName: string, callback: (data: any) => void): void {
37
- this.emitter.on(eventName, callback);
38
- }
39
-
40
- /**
41
- * 取消订阅事件
42
- * @param eventName 事件名称
43
- * @param callback 回调函数
44
- */
45
- unsubscribe(eventName: string, callback: (data: any) => void): void {
46
- this.emitter.off(eventName, callback);
47
- }
48
-
49
- /**
50
- * 只订阅一次事件
51
- * @param eventName 事件名称
52
- * @param callback 回调函数
53
- */
54
- subscribeOnce(eventName: string, callback: (data: any) => void): void {
55
- this.emitter.once(eventName, callback);
56
- }
57
- }
58
-
59
- // 创建单例实例
60
- const eventBus = new EventBus();
61
-
62
- export default eventBus;
@@ -1,85 +0,0 @@
1
- // In-memory queue service implementation
2
- // This is a memory-based alternative to the Redis queue service
3
-
4
- const queue_name = process.env.QUEUE_NAME || "tasks"; // Queue name, local development needs to configure its own queue
5
-
6
- // In-memory storage for queues: Map<queue_name, message[]>
7
- // Using Map to support multiple queues (e.g., per tenant)
8
- const queues = new Map<string, any[]>();
9
-
10
- // Initialize queue if it doesn't exist
11
- const ensureQueue = (queueName: string): void => {
12
- if (!queues.has(queueName)) {
13
- queues.set(queueName, []);
14
- }
15
- };
16
-
17
- // Enqueue Message (equivalent to lPush - push to left/beginning)
18
- const sendToQueue = async (queueName: string, message: any) => {
19
- try {
20
- ensureQueue(queueName);
21
- const queue = queues.get(queueName)!;
22
-
23
- // lPush behavior: add to the beginning of the array
24
- queue.unshift(message);
25
-
26
- const result = queue.length;
27
- console.log("lPush (memory)", result);
28
- return { data: result, error: null };
29
- } catch (error) {
30
- console.error(error);
31
- return { data: null, error };
32
- }
33
- };
34
-
35
- // Dequeue Message (equivalent to rPop - pop from right/end)
36
- const popFromQueue = async (queueName: string) => {
37
- try {
38
- ensureQueue(queueName);
39
- const queue = queues.get(queueName)!;
40
-
41
- // rPop behavior: remove from the end of the array
42
- // This creates FIFO behavior when combined with lPush (unshift + pop = FIFO)
43
- const message = queue.pop();
44
-
45
- if (message) {
46
- return { data: message, error: null };
47
- }
48
- return { data: null, error: null };
49
- } catch (error) {
50
- console.error(error);
51
- return { data: null, error };
52
- }
53
- };
54
-
55
- const createTenantQueue = async () => {
56
- // Initialize the queue in memory
57
- try {
58
- ensureQueue(queue_name);
59
- const queue = queues.get(queue_name)!;
60
- const exists = queue !== undefined;
61
- return { success: true, queue_name };
62
- } catch (error) {
63
- console.error(error);
64
- return { success: false, error };
65
- }
66
- };
67
-
68
- export const pushAgentTaskToQueue = async (agentTask: any) => {
69
- const tenantId = agentTask["x-tenant-id"];
70
-
71
- try {
72
- await createTenantQueue();
73
- const result = await sendToQueue(`${queue_name}`, agentTask);
74
- return result;
75
- } catch (error) {
76
- console.error(error);
77
- return null;
78
- }
79
- };
80
-
81
- export const popAgentTaskFromQueue = async () => {
82
- const result = await popFromQueue(`${queue_name}`);
83
- return result;
84
- };
85
-
@@ -1,116 +0,0 @@
1
- import { createClient, RedisClientType } from "redis";
2
-
3
- // Redis queue service implementation
4
- // This is a Redis-based queue service
5
-
6
- const queue_name = process.env.QUEUE_NAME || "tasks"; // Queue name, local development needs to configure its own queue
7
-
8
- // Redis client - initialized lazily only when needed
9
- let redisClient: RedisClientType | null = null;
10
- let isConnecting = false;
11
- let connectionPromise: Promise<void> | null = null;
12
-
13
- // Lazy initialization of Redis client
14
- const getRedisClient = async (): Promise<RedisClientType> => {
15
- // If client is already connected, return it
16
- if (redisClient?.isOpen) {
17
- return redisClient;
18
- }
19
-
20
- // If connection is in progress, wait for it
21
- if (isConnecting && connectionPromise) {
22
- await connectionPromise;
23
- if (redisClient?.isOpen) {
24
- return redisClient;
25
- }
26
- }
27
-
28
- // Create and connect to Redis client
29
- isConnecting = true;
30
- connectionPromise = (async () => {
31
- try {
32
- const redisOptions: any = {
33
- url: process.env.REDIS_URL || "redis://localhost:6379",
34
- password: process.env.REDIS_PASSWORD,
35
- };
36
-
37
- redisClient = createClient(redisOptions) as RedisClientType;
38
-
39
- redisClient.on("error", (err: Error) =>
40
- console.error("Redis Client Error", err)
41
- );
42
-
43
- await redisClient.connect();
44
- console.log("Redis connection successful");
45
- isConnecting = false;
46
- } catch (error) {
47
- console.error("Redis connection failed:", error);
48
- isConnecting = false;
49
- throw error;
50
- }
51
- })();
52
-
53
- await connectionPromise;
54
- return redisClient!;
55
- };
56
-
57
- // Enqueue Message
58
- const sendToQueue = async (queueName: string, message: any) => {
59
- try {
60
- const client = await getRedisClient();
61
- // Push message to queue
62
- const result = await client.lPush(queueName, JSON.stringify(message));
63
- console.log("lPush", result);
64
- return { data: result, error: null };
65
- } catch (error) {
66
- console.error(error);
67
- return { data: null, error };
68
- }
69
- };
70
-
71
- // Dequeue Message
72
- const popFromQueue = async (queueName: string) => {
73
- try {
74
- const client = await getRedisClient();
75
- // Get message from queue
76
- const message = await client.rPop(queueName);
77
- if (message) {
78
- return { data: JSON.parse(message), error: null };
79
- }
80
- return { data: null, error: null };
81
- } catch (error) {
82
- console.error(error);
83
- return { data: null, error };
84
- }
85
- };
86
-
87
- const createTenantQueue = async () => {
88
- // Redis doesn't need explicit queue creation, but we keep this function for API compatibility
89
- // Can perform some initialization operations, such as checking if queue exists
90
- try {
91
- const client = await getRedisClient();
92
- const exists = await client.exists(queue_name);
93
- return { success: true, queue_name };
94
- } catch (error) {
95
- console.error(error);
96
- return { success: false, error };
97
- }
98
- };
99
-
100
- export const pushAgentTaskToQueue = async (agentTask: any) => {
101
- const tenantId = agentTask["x-tenant-id"];
102
-
103
- try {
104
- await createTenantQueue();
105
- const result = await sendToQueue(`${queue_name}`, agentTask);
106
- return result;
107
- } catch (error) {
108
- console.error(error);
109
- return null;
110
- }
111
- };
112
-
113
- export const popAgentTaskFromQueue = async () => {
114
- const result = await popFromQueue(`${queue_name}`);
115
- return result;
116
- };