zig-pay/src/services/service.zig
2025-08-07 22:07:35 -03:00

80 lines
2.2 KiB
Zig

const std = @import("std");
const mem = std.mem;
const heap = std.heap;
const net = std.net;
const Allocator = mem.Allocator;
const Stream = net.Stream;
const Thread = std.Thread;
const Mutex = Thread.Mutex;
const Address = net.Address;
const FakeStream = @import("helpers").FakeStream;
const is_test = @import("builtin").is_test;
const testing = std.testing;
const expect = testing.expect;
pub const ServiceConnectionStatus = enum { closed, disponible, ocuppied };
pub const ServiceConnection = struct {
stream: if (is_test) FakeStream else Stream = undefined,
status: ServiceConnectionStatus = .closed,
pub fn readAsHttp(self: *ServiceConnection, buf: []u8) usize {
var res_len: usize = 0;
while (true) { // trying clean the stream
const aux_len = self.stream.read(buf[res_len..]) catch 0;
if (aux_len == 0) {
break;
}
res_len += aux_len;
if (res_len > 3 and buf[res_len - 1] == '\n' and buf[res_len - 2] == '\r' and buf[res_len - 3] == '\n' and buf[res_len - 4] == '\r') {
break;
}
}
return res_len;
}
pub fn tryConnect(self: *ServiceConnection, address: *const Address) !void {
if (is_test) {
const buf = try testing.allocator.alloc(u8, 1024);
self.stream = FakeStream.init(buf);
} else {
self.stream = try net.tcpConnectToAddress(address.*);
}
}
pub fn close(self: *ServiceConnection) void {
if (self.status == .closed) {
return;
}
if (is_test) {
testing.allocator.free(self.stream.buffer);
} else {
self.stream.close();
}
self.status = .closed;
}
};
pub const ServiceHealth = enum { available, unavailable };
pub const ServiceError = error{ NotFound, Unreachable, NumConnectionsShouldBeMultipleOfTen } || Allocator.Error;
pub const TicketStatus = enum { new, pending, success, try_again, ack };
pub const ServiceTicket = struct {
content: []const u8,
status: TicketStatus = .ack,
conn: *ServiceConnection = undefined,
res_buf: [1024]u8 = undefined,
service_id: u64 = 0,
};