fix cache related segfault

This commit is contained in:
Emil Lerch 2026-01-02 15:06:35 -08:00
parent 7fd9810c78
commit ede8b593b8
Signed by: lobo
GPG key ID: A7B62D657EF764F8
2 changed files with 40 additions and 6 deletions

42
src/cache/Cache.zig vendored
View file

@ -14,18 +14,21 @@ pub const Config = struct {
cache_dir: []const u8,
};
pub fn init(allocator: std.mem.Allocator, config: Config) !Cache {
pub fn init(allocator: std.mem.Allocator, config: Config) !*Cache {
std.fs.makeDirAbsolute(config.cache_dir) catch |err| {
if (err != error.PathAlreadyExists) return err;
};
var cache = Cache{
const cache = try allocator.create(Cache);
errdefer allocator.destroy(cache);
cache.* = Cache{
.allocator = allocator,
.lru = try Lru.init(allocator, config.max_entries),
.cache_dir = try allocator.dupe(u8, config.cache_dir),
};
cache.lru.setEvictionCallback(&cache, evictCallback);
cache.lru.setEvictionCallback(cache, evictCallback);
// Clean up expired files and populate L1 cache from L2
cache.loadFromDir() catch |err| {
@ -69,6 +72,7 @@ pub fn put(self: *Cache, key: []const u8, value: []const u8, ttl_seconds: u64) !
pub fn deinit(self: *Cache) void {
self.lru.deinit();
self.allocator.free(self.cache_dir);
self.allocator.destroy(self);
}
fn getCacheFilename(self: *Cache, key: []const u8) ![]const u8 {
@ -247,7 +251,7 @@ test "L1/L2 cache flow" {
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
const cache_dir = try tmp_dir.dir.realpath(".", &path_buf);
var cache = try Cache.init(allocator, .{ .max_entries = 10, .cache_dir = cache_dir });
const cache = try Cache.init(allocator, .{ .max_entries = 10, .cache_dir = cache_dir });
defer cache.deinit();
// Put item in cache
@ -271,3 +275,33 @@ test "L1/L2 cache flow" {
// Now it should be in L1
try std.testing.expectEqualStrings("value1", cache.lru.get("key1").?);
}
test "expired cache entry returns null" {
const allocator = std.testing.allocator;
var tmp_dir = std.testing.tmpDir(.{});
defer tmp_dir.cleanup();
var path_buf: [std.fs.max_path_bytes]u8 = undefined;
const cache_dir = try tmp_dir.dir.realpath(".", &path_buf);
const cache = try Cache.init(allocator, .{ .max_entries = 10, .cache_dir = cache_dir });
defer cache.deinit();
// Put item with past expiration time
const now = std.time.milliTimestamp();
const past_expires = now - 1000;
// Manually insert expired entry into L1
const key_copy = try allocator.dupe(u8, "key1");
const value_copy = try allocator.dupe(u8, "value1");
try cache.lru.map.put(key_copy, .{
.value = value_copy,
.expires = past_expires,
.access_count = 0,
});
// Get should return null for expired entry
const result = cache.get("key1");
try std.testing.expect(result == null);
}

View file

@ -49,7 +49,7 @@ pub fn main() !void {
// Initialize location resolver
var resolver = Resolver.init(allocator, &geoip, &geocache, &airports_db);
var cache = try Cache.init(allocator, .{
const cache = try Cache.init(allocator, .{
.max_entries = cfg.cache_size,
.cache_dir = cfg.cache_dir,
});
@ -66,7 +66,7 @@ pub fn main() !void {
defer metno.deinit();
var server = try Server.init(allocator, cfg.listen_host, cfg.listen_port, .{
.provider = metno.provider(&cache),
.provider = metno.provider(cache),
.resolver = &resolver,
.geoip = &geoip,
}, &rate_limiter);