Skip to content

Commit 1eaffc4

Browse files
pxp9claude
andcommitted
refactor: extract generic Queue to utils.zig
- create generic Queue(T) function for thread-safe request queues - replace TelegramQueue and AiQueue with Queue type aliases - rename methods to post/next for consistency Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
1 parent 08f037b commit 1eaffc4

File tree

4 files changed

+54
-75
lines changed

4 files changed

+54
-75
lines changed

src/ai.zig

Lines changed: 2 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -140,37 +140,7 @@ pub const AiRequest = union(AiRequestKind) {
140140
shutdown: void,
141141
};
142142

143-
pub const AiQueue = struct {
144-
mutex: std.Thread.Mutex = .{},
145-
requests: std.ArrayList(AiRequest),
146-
alloc: std.mem.Allocator,
147-
148-
pub fn init(alloc: std.mem.Allocator) AiQueue {
149-
return .{
150-
.requests = .empty,
151-
.alloc = alloc,
152-
};
153-
}
154-
155-
pub fn deinit(self: *AiQueue) void {
156-
self.requests.deinit(self.alloc);
157-
}
158-
159-
pub fn postRequest(self: *AiQueue, request: AiRequest) !void {
160-
self.mutex.lock();
161-
defer self.mutex.unlock();
162-
try self.requests.append(self.alloc, request);
163-
}
164-
165-
pub fn getRequest(self: *AiQueue) ?AiRequest {
166-
self.mutex.lock();
167-
defer self.mutex.unlock();
168-
if (self.requests.items.len == 0) return null;
169-
const request = self.requests.items[0];
170-
_ = self.requests.orderedRemove(0);
171-
return request;
172-
}
173-
};
143+
pub const AiQueue = utils.AiQueue;
174144

175145
pub const MessageRole = enum {
176146
user,
@@ -195,7 +165,7 @@ pub fn aiAgentLoop(ctx: utils.AiThreadContext) void {
195165
}
196166

197167
while (true) {
198-
const req = ctx.request_queue.getRequest() orelse {
168+
const req = ctx.request_queue.next() orelse {
199169
std.Thread.yield() catch {};
200170
continue;
201171
};

src/main.zig

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ pub fn main() !void {
150150
}
151151

152152
std.log.info("Requesting chats from Telegram...", .{});
153-
try telegram_queue.postRequest(.{ .load_chats = .{ .count = 20 } });
153+
try telegram_queue.post(.{ .load_chats = .{ .count = 20 } });
154154

155155
var selected_chat_idx: usize = 0;
156156

@@ -296,7 +296,7 @@ fn handle_event(alloc: std.mem.Allocator, event: Event, state: *AppState) !i32 {
296296

297297
if (state.chats.items.len > 0) {
298298
const first_chat = state.chats.items[0];
299-
try state.telegram_queue.postRequest(.{
299+
try state.telegram_queue.post(.{
300300
.load_chat_history = .{
301301
.chat_id = first_chat.id,
302302
.limit = 10,
@@ -486,7 +486,7 @@ fn applyAiUpdateResult(alloc: std.mem.Allocator, state: *AppState, result: ai.Ai
486486
},
487487
.send_telegram => |msg| {
488488
const text_copy = try alloc.dupe(u8, msg.text);
489-
try state.telegram_queue.postRequest(.{
489+
try state.telegram_queue.post(.{
490490
.send_message = .{ .chat_id = msg.chat_id, .text = text_copy },
491491
});
492492
},
@@ -495,7 +495,7 @@ fn applyAiUpdateResult(alloc: std.mem.Allocator, state: *AppState, result: ai.Ai
495495
try std.fmt.allocPrint(alloc, "Message sent successfully to chat '{s}'", .{res.message})
496496
else
497497
try std.fmt.allocPrint(alloc, "Chat '{s}' not found in your conversations", .{res.message});
498-
try state.ai_queue.postRequest(.{ .tool_result = .{ .success = res.success, .message = message } });
498+
try state.ai_queue.post(.{ .tool_result = .{ .success = res.success, .message = message } });
499499
},
500500
}
501501
}
@@ -542,7 +542,7 @@ fn handle_select_action(alloc: std.mem.Allocator, state: *AppState) !void {
542542
if (!state.chat_messages_cache.contains(selected_chat.id)) {
543543
std.log.info("Requesting messages for chat: {s}", .{selected_chat.title});
544544
state.loading_messages.* = true;
545-
try state.telegram_queue.postRequest(.{
545+
try state.telegram_queue.post(.{
546546
.load_chat_history = .{ .chat_id = selected_chat.id, .limit = 10 },
547547
});
548548
}
@@ -554,7 +554,7 @@ fn handle_select_action(alloc: std.mem.Allocator, state: *AppState) !void {
554554
const selected_chat = state.chats.items[state.selected_chat_idx.*];
555555
const message_text = try state.chat_input.toOwnedSlice();
556556
std.log.info("Sending message to chat {d}", .{selected_chat.id});
557-
try state.telegram_queue.postRequest(.{
557+
try state.telegram_queue.post(.{
558558
.send_message = .{ .chat_id = selected_chat.id, .text = message_text },
559559
});
560560
},
@@ -634,7 +634,7 @@ fn handle_select_action(alloc: std.mem.Allocator, state: *AppState) !void {
634634
const enhanced_prompt = try chat_list.toOwnedSlice(alloc);
635635

636636
state.llm_loading.* = true;
637-
try state.ai_queue.postRequest(.{ .send_message = .{ .prompt = enhanced_prompt } });
637+
try state.ai_queue.post(.{ .send_message = .{ .prompt = enhanced_prompt } });
638638
},
639639
}
640640
}
@@ -718,8 +718,8 @@ fn handle_key_action(alloc: std.mem.Allocator, state: *AppState, action: keybind
718718
switch (action) {
719719
.quit => {
720720
std.log.info("Quit requested, shutting down threads", .{});
721-
state.telegram_queue.postRequest(.{ .shutdown = {} }) catch {};
722-
state.ai_queue.postRequest(.{ .shutdown = {} }) catch {};
721+
state.telegram_queue.post(.{ .shutdown = {} }) catch {};
722+
state.ai_queue.post(.{ .shutdown = {} }) catch {};
723723
return 0;
724724
},
725725
.switch_mode => state.active_mode.* = switch (state.active_mode.*) {

src/telegram.zig

Lines changed: 2 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -500,39 +500,11 @@ pub const TelegramRequest = union(TelegramRequestKind) {
500500
shutdown: void,
501501
};
502502

503-
pub const TelegramQueue = struct {
504-
mutex: std.Thread.Mutex = .{},
505-
requests: std.ArrayList(TelegramRequest),
506-
alloc: std.mem.Allocator,
507-
508-
pub fn init(alloc: std.mem.Allocator) TelegramQueue {
509-
return .{
510-
.requests = .empty,
511-
.alloc = alloc,
512-
};
513-
}
514-
515-
pub fn deinit(self: *TelegramQueue) void {
516-
self.requests.deinit(self.alloc);
517-
}
518-
519-
pub fn postRequest(self: *TelegramQueue, request: TelegramRequest) !void {
520-
self.mutex.lock();
521-
defer self.mutex.unlock();
522-
try self.requests.append(self.alloc, request);
523-
}
524-
525-
pub fn nextRequest(self: *TelegramQueue) ?TelegramRequest {
526-
self.mutex.lock();
527-
defer self.mutex.unlock();
528-
if (self.requests.items.len == 0) return null;
529-
return self.requests.orderedRemove(0);
530-
}
531-
};
503+
pub const TelegramQueue = utils.TelegramQueue;
532504

533505
pub fn telegramUpdateLoop(ctx: utils.TelegramThreadContext) void {
534506
while (true) {
535-
while (ctx.request_queue.nextRequest()) |request| {
507+
while (ctx.request_queue.next()) |request| {
536508
switch (request) {
537509
.load_chats => |req| {
538510
std.log.info("Processing load_chats request, count={d}", .{req.count});

src/utils.zig

Lines changed: 41 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -20,17 +20,20 @@ pub const Event = union(enum) {
2020
ai_update: ai.AiUpdate,
2121
};
2222

23+
pub const TelegramQueue = Queue(telegram.TelegramRequest);
24+
pub const AiQueue = Queue(ai.AiRequest);
25+
2326
pub const TelegramThreadContext = struct {
2427
client: *tdlib.Client,
2528
loop: *vaxis.Loop(Event),
26-
request_queue: *telegram.TelegramQueue,
29+
request_queue: *TelegramQueue,
2730
alloc: std.mem.Allocator,
2831
};
2932

3033
pub const AiThreadContext = struct {
3134
config: *ai.Config,
3235
loop: *vaxis.Loop(Event),
33-
request_queue: *ai.AiQueue,
36+
request_queue: *AiQueue,
3437
alloc: std.mem.Allocator,
3538
};
3639

@@ -40,6 +43,40 @@ pub const InputMode = enum {
4043
chat_list,
4144
};
4245

46+
pub fn Queue(comptime T: type) type {
47+
return struct {
48+
const Self = @This();
49+
50+
mutex: std.Thread.Mutex = .{},
51+
requests: std.ArrayList(T),
52+
alloc: std.mem.Allocator,
53+
54+
pub fn init(alloc: std.mem.Allocator) Self {
55+
return .{
56+
.requests = .empty,
57+
.alloc = alloc,
58+
};
59+
}
60+
61+
pub fn deinit(self: *Self) void {
62+
self.requests.deinit(self.alloc);
63+
}
64+
65+
pub fn post(self: *Self, request: T) !void {
66+
self.mutex.lock();
67+
defer self.mutex.unlock();
68+
try self.requests.append(self.alloc, request);
69+
}
70+
71+
pub fn next(self: *Self) ?T {
72+
self.mutex.lock();
73+
defer self.mutex.unlock();
74+
if (self.requests.items.len == 0) return null;
75+
return self.requests.orderedRemove(0);
76+
}
77+
};
78+
}
79+
4380
pub const AppState = struct {
4481
vx: *vaxis.Vaxis,
4582
tty: *vaxis.Tty,
@@ -53,8 +90,8 @@ pub const AppState = struct {
5390
llm_loading: *bool,
5491
keybindings: *keybindings.KeyBindings,
5592
keymap: *keybindings.ModeKeymap,
56-
telegram_queue: *telegram.TelegramQueue,
57-
ai_queue: *ai.AiQueue,
93+
telegram_queue: *TelegramQueue,
94+
ai_queue: *AiQueue,
5895
chat_list_text_view: *TextView,
5996
chat_list_text_buffer: *TextViewBuffer,
6097
chat_text_view: *TextView,

0 commit comments

Comments
 (0)