parent
dbe487e0f4
commit
704be793a5
1 changed files with 11 additions and 40 deletions
51
src/main.zig
51
src/main.zig
|
|
@ -508,31 +508,27 @@ fn writeNewPortfolio(io: std.Io, allocator: std.mem.Allocator, path: []const u8,
|
|||
|
||||
// ── Refresh command ──────────────────────────────────────────
|
||||
|
||||
fn refresh(
|
||||
io: std.Io,
|
||||
gpa: std.mem.Allocator,
|
||||
environ: *const std.process.Environ.Map,
|
||||
) !void {
|
||||
var config = zfin.Config.fromEnv(io, gpa, environ);
|
||||
fn refresh(io: std.Io, allocator: std.mem.Allocator, environ: *const std.process.Environ.Map) !void {
|
||||
var config = zfin.Config.fromEnv(io, allocator, environ);
|
||||
defer config.deinit();
|
||||
var svc = zfin.DataService.init(io, gpa, config);
|
||||
var svc = zfin.DataService.init(io, allocator, config);
|
||||
defer svc.deinit();
|
||||
|
||||
const portfolio_path = environ.get("ZFIN_PORTFOLIO") orelse "portfolio.srf";
|
||||
|
||||
const data = std.Io.Dir.cwd().readFileAlloc(io, portfolio_path, gpa, .limited(10 * 1024 * 1024)) catch {
|
||||
const data = std.Io.Dir.cwd().readFileAlloc(io, portfolio_path, allocator, .limited(10 * 1024 * 1024)) catch {
|
||||
log.err("failed to read portfolio: {s}", .{portfolio_path});
|
||||
return error.ReadFailed;
|
||||
};
|
||||
defer gpa.free(data);
|
||||
defer allocator.free(data);
|
||||
|
||||
var portfolio = zfin.cache.deserializePortfolio(gpa, data) catch {
|
||||
var portfolio = zfin.cache.deserializePortfolio(allocator, data) catch {
|
||||
log.err("failed to parse portfolio", .{});
|
||||
return error.ParseFailed;
|
||||
};
|
||||
defer portfolio.deinit();
|
||||
|
||||
var symbols = std.StringHashMap(void).init(gpa);
|
||||
var symbols = std.StringHashMap(void).init(allocator);
|
||||
defer symbols.deinit();
|
||||
for (portfolio.lots) |lot| {
|
||||
if (lot.security_type != .stock and lot.security_type != .watch) continue;
|
||||
|
|
@ -581,25 +577,6 @@ fn refresh(
|
|||
try stdout.flush();
|
||||
}
|
||||
|
||||
// Per-iteration scratch arena. Wraps the gpa so iteration-scoped
|
||||
// allocations get freed in bulk via `reset(.retain_capacity)` at
|
||||
// the bottom of each loop iteration — no per-allocation defers,
|
||||
// no manual `free` mistakes. Capacity is retained so we're not
|
||||
// re-acquiring pages every symbol.
|
||||
//
|
||||
// What goes through this arena: any per-iteration scratch we
|
||||
// allocate ourselves (CIK dupes, future symbol-derived strings).
|
||||
// NOT the `FetchResult` payloads — those are owned by the
|
||||
// service's gpa and freed via `result.deinit()` at their own
|
||||
// call sites.
|
||||
//
|
||||
// We don't use juicy-main's `init.arena` because that's
|
||||
// process-lifetime; resetting it mid-run would clobber other
|
||||
// startup allocations.
|
||||
var iter_arena_state = std.heap.ArenaAllocator.init(gpa);
|
||||
defer iter_arena_state.deinit();
|
||||
const iter_arena = iter_arena_state.allocator();
|
||||
|
||||
var it = symbols.iterator();
|
||||
while (it.next()) |entry| {
|
||||
const sym = entry.key_ptr.*;
|
||||
|
|
@ -660,16 +637,14 @@ fn refresh(
|
|||
// had it — used to chain into entity_facts below.
|
||||
// NotFound is logged as `n/a` (symbol genuinely has no
|
||||
// Wikidata entry) and doesn't flip sym_ok.
|
||||
//
|
||||
// The CIK dupe goes through `iter_arena`. No defer-free
|
||||
// needed — the arena is reset at end of iteration.
|
||||
var cik_str: ?[]const u8 = null;
|
||||
var cik_buf: ?[]u8 = null;
|
||||
defer if (cik_buf) |b| allocator.free(b);
|
||||
try printRateLimitWait(&svc, stdout);
|
||||
if (svc.getClassification(sym, .{})) |result| {
|
||||
defer result.deinit();
|
||||
if (result.data.len > 0) {
|
||||
if (result.data[0].cik) |cik| {
|
||||
cik_str = iter_arena.dupe(u8, cik) catch null;
|
||||
cik_buf = allocator.dupe(u8, cik) catch null;
|
||||
}
|
||||
}
|
||||
try stdout.print(", classification ok", .{});
|
||||
|
|
@ -703,7 +678,7 @@ fn refresh(
|
|||
// have an EDGAR CIK from the ticker map (production
|
||||
// zfin chains entity_facts off Wikidata's CIK, so the
|
||||
// server warms the cache the same way).
|
||||
if (cik_str) |cik| {
|
||||
if (cik_buf) |cik| {
|
||||
try printRateLimitWait(&svc, stdout);
|
||||
if (svc.getEntityFacts(cik, .{})) |result| {
|
||||
result.deinit();
|
||||
|
|
@ -721,10 +696,6 @@ fn refresh(
|
|||
try stdout.flush();
|
||||
|
||||
if (sym_ok) success_count += 1 else fail_count += 1;
|
||||
|
||||
// Reset per-iteration scratch. Retains capacity so the
|
||||
// next iteration's allocations reuse the same pages.
|
||||
_ = iter_arena_state.reset(.retain_capacity);
|
||||
}
|
||||
|
||||
try stdout.print("\nRefresh complete: {d} ok, {d} failed\n", .{ success_count, fail_count });
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue