wttr/src/main.zig

103 lines
3.4 KiB
Zig

const std = @import("std");
const Config = @import("Config.zig");
const Cache = @import("cache/Cache.zig");
const MetNo = @import("weather/MetNo.zig");
const Server = @import("http/Server.zig");
const RateLimiter = @import("http/RateLimiter.zig");
const GeoIp = @import("location/GeoIp.zig");
const GeoCache = @import("location/GeoCache.zig");
const Airports = @import("location/Airports.zig");
const Resolver = @import("location/resolver.zig").Resolver;
const GeoLite2 = @import("location/GeoLite2.zig");
const version = @import("build_options").version;
pub fn main() !u8 {
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
defer _ = gpa.deinit();
const allocator = gpa.allocator();
const cfg = try Config.load(allocator);
defer cfg.deinit(allocator);
std.log.info("wttr version {s} starting on {s}:{d}", .{ version, cfg.listen_host, cfg.listen_port });
std.log.info("Cache size: {d}", .{cfg.cache_size});
std.log.info("Cache dir: {s}", .{cfg.cache_dir});
std.log.info("GeoLite2 path: {s}", .{cfg.geolite_path});
if (cfg.geocache_file) |f| {
std.log.info("Geocache file: {s}", .{f});
} else {
std.log.info("Geocache: in-memory only", .{});
}
var metno = MetNo.init(allocator, null) catch |err| {
if (err == MetNo.MissingIdentificationError) return 1;
return err;
};
defer metno.deinit();
// Ensure GeoLite2 database exists
try GeoLite2.ensureDatabase(allocator, cfg.geolite_path);
// Initialize GeoIP database with optional IP2Location fallback
var geoip = GeoIp.init(
allocator,
cfg.geolite_path,
cfg.ip2location_api_key,
if (cfg.ip2location_api_key != null) cfg.ip2location_cache_file else null,
) catch |err| {
std.log.err("Failed to load GeoIP database from {s}: {}", .{ cfg.geolite_path, err });
return err;
};
defer geoip.deinit();
// Initialize geocoding cache
var geocache = try GeoCache.init(allocator, cfg.geocache_file);
defer geocache.deinit();
// Initialize airports database
var airports_db = try Airports.init(allocator);
defer airports_db.deinit();
// Initialize location resolver
var resolver = Resolver.init(allocator, &geoip, &geocache, &airports_db);
const cache = try Cache.init(allocator, .{
.max_entries = cfg.cache_size,
.cache_dir = cfg.cache_dir,
});
defer cache.deinit();
var rate_limiter = try RateLimiter.init(allocator, .{
.capacity = 300,
.refill_rate = 5,
.refill_interval_ms = 200,
});
defer rate_limiter.deinit();
var server = try Server.init(allocator, cfg.listen_host, cfg.listen_port, .{
.provider = metno.provider(cache),
.resolver = &resolver,
.geoip = &geoip,
}, &rate_limiter);
try server.listen();
return 0;
}
test {
std.testing.refAllDecls(@This());
_ = @import("Config.zig");
_ = @import("cache/Lru.zig");
_ = @import("weather/Mock.zig");
_ = @import("http/RateLimiter.zig");
_ = @import("http/query.zig");
_ = @import("http/help.zig");
_ = @import("render/line.zig");
_ = @import("render/json.zig");
_ = @import("render/v2.zig");
_ = @import("render/custom.zig");
_ = @import("location/GeoIp.zig");
_ = @import("location/GeoCache.zig");
_ = @import("location/Airports.zig");
_ = @import("location/resolver.zig");
}