Skip to documentation
SLOP

tiny.smg.command.check.refresh

Reference tiny.smg command check refresh

Defined in command.check.

API (1)

Actions

Public operations.

No direct callersNo direct callscommand.checkrefresh
Static calls · unresolved targets: unknown · external targets: unknown.

Source

Called byCallsNo direct callersprivate; no linktools.smg.src.command.check.refreshrunConfiguredcommand.check.refreshrun
Static calls · unresolved targets: 0 · external targets: 3.

Source: tools/smg/src/command/check/refresh.zig

zig
const std = @import("std");const sql = @import("sql");const sys = @import("sys");const smg = @import("../../root.zig");const concepts = smg.concepts;const graph_mod = smg.graph;const scanner = smg.scan;const cli_options = smg.cli.options;const cli_output = smg.cli.output;const cli_scan = smg.command.scan;const cli_validation = smg.cli.validation;const storage = smg.storage;const runner = @import("run.zig");const ScanMode = enum { full, changed, matched };const signature = "[OPTIONS]";pub fn run(allocator: std.mem.Allocator, phases: std.mem.Allocator, args: []const []const u8, base_limits: smg.Limits) !u8 {    if (try cli_validation.rejectMissingOptionValues(allocator, args, &.{        cli_options.max_source_file_bytes_option,        cli_options.max_fragment_bytes_option,        cli_options.max_git_file_list_bytes_option,        cli_options.wal_recovery_limit_bytes_option,    })) return 2;    const limits = (try cli_validation.configuredLimitsOrReject(        allocator,        "refresh-check",        signature,        args,        base_limits,    )) orelse return 2;    return runConfigured(allocator, phases, args, limits) catch |err| switch (err) {        error.MaxSourceFileBytesExceeded => try cli_output.writeByteLimitExceeded(            allocator,            "max_source_file_bytes",            limits.scan.max_source_file_bytes,            cli_options.max_source_file_bytes_option,        ),        error.MaxFragmentBytesExceeded => try cli_output.writeByteLimitExceeded(            allocator,            "max_fragment_bytes",            limits.scan.max_fragment_bytes,            cli_options.max_fragment_bytes_option,        ),        error.MaxGitFileListBytesExceeded => try cli_output.writeByteLimitExceeded(            allocator,            "max_git_file_list_bytes",            limits.scan.max_git_file_list_bytes,            cli_options.max_git_file_list_bytes_option,        ),        error.WalRecoveryLimitBytesExceeded => try cli_output.writeByteLimitExceeded(            allocator,            "wal_recovery_limit_bytes",            limits.storage.wal_recovery_limit_bytes,            cli_options.wal_recovery_limit_bytes_option,        ),        else => return err,    };}fn runConfigured(allocator: std.mem.Allocator, phases: std.mem.Allocator, args: []const []const u8, limits: smg.Limits) !u8 {    const total_started = sys.time.nanoTimestamp();    var phase_started = total_started;    const root = try storage.initProject(allocator, null, limits.storage);    const rules_path = try storage.files.rulesPath(allocator, root);    try cli_output.writeErr(try cli_scan.refreshStartLine(allocator, root, rules_path));    const source = try loadSource(allocator, phases, root, limits.storage);    const snapshot_ns = elapsedNanoseconds(&phase_started);    var refreshed = try refreshGraph(allocator, phases, root, source.head, limits);    defer refreshed.manifest.deinit();    const source_verify_ns = try verifySource(allocator, phases, root, &refreshed, limits);    if (cli_options.hasFlag(args, "--scan") or cli_options.hasFlag(args, "--full")) {        _ = try cli_output.writeOut(try cli_scan.renderText(            allocator,            refreshed.stats,            cli_options.hasFlag(args, "--full"),        ));    }    try cli_output.writeErr("refresh-check: check rules\n");    phase_started = sys.time.nanoTimestamp();    const result = try runner.run(allocator, root, refreshed.graph, source.concepts, args, limits);    const rule_ns = elapsedNanoseconds(&phase_started);    if (cli_options.hasFlag(args, "--timing")) {        try cli_output.writeErr(try timingLine(allocator, .{            .total_ns = sinceNanoseconds(total_started),            .snapshot_ns = snapshot_ns,            .source_state_ns = refreshed.source_state_ns,            .graph_load_ns = refreshed.graph_load_ns,            .scan_ns = refreshed.scan_ns,            .source_verify_ns = source_verify_ns,            .scan_mode = refreshed.mode,            .cache = refreshed.cache_timing,            .publish = refreshed.publish,            .rule_ns = rule_ns,        }));    }    return result;}const SourceSnapshot = struct {    head: sql.Hash,    concepts: []const concepts.Concept,};fn loadSource(    allocator: std.mem.Allocator,    phases: std.mem.Allocator,    root: []const u8,    limits: smg.StorageLimits,) !SourceSnapshot {    var opened = try storage.store.openRead(phases, root, limits);    defer opened.close();    return .{        .head = opened.reader.head,        .concepts = try concepts.loadFromReader(allocator, &opened.reader),    };}const RefreshedGraph = struct {    graph: graph_mod.Graph,    stats: scanner.Stats,    project: ?scanner.scan_files.ProjectState,    executable: ?scanner.scan_files.SourceDigest,    manifest: scanner.fragment.Manifest,    mode: ScanMode,    cache_timing: scanner.CachedProjectTiming,    publish: storage.graph.PublishTiming,    source_state_ns: u64,    graph_load_ns: u64,    scan_ns: u64,};fn refreshGraph(    allocator: std.mem.Allocator,    phases: std.mem.Allocator,    root: []const u8,    head: sql.Hash,    limits: smg.Limits,) !RefreshedGraph {    var phase_started = sys.time.nanoTimestamp();    const executable = storage.source.executableDigest(allocator) catch null;    const stored_project = if (executable) |identity|        try storage.source.projectForOwner(allocator, root, head, identity)    else        null;    const project = scanner.scan_files.projectState(allocator, phases, root, &.{}, limits.scan) catch null;    var manifest = if (executable) |identity|        try scanner.fragment.loadManifest(allocator, phases, root, identity, limits.scan)    else        scanner.fragment.Manifest.empty(allocator);    errdefer manifest.deinit();    const mode: ScanMode = if (stored_project != null and project != null and        std.mem.eql(u8, &stored_project.?, &project.?.project.digest))        .matched    else if (stored_project != null and project != null and manifest.matchesProject(stored_project.?))        .changed    else        .full;    const changed_paths: []const []const u8 = if (mode == .changed)        try manifest.changedPaths(allocator, root, project.?.sources)    else        &.{};    const source_state_ns = elapsedNanoseconds(&phase_started);    var graph = switch (mode) {        .full => graph_mod.init(allocator),        .changed, .matched => try storage.graph.load(allocator, phases, root, limits.storage),    };    const graph_load_ns = elapsedNanoseconds(&phase_started);    var cache_timing: scanner.CachedProjectTiming = .{};    const stats = try scanGraph(        allocator,        phases,        &graph,        root,        project,        executable,        changed_paths,        mode,        &cache_timing,        limits,    );    const scan_ns = elapsedNanoseconds(&phase_started);    try writeProgress(allocator, mode, stats, changed_paths.len, project);    const publish = switch (mode) {        .full, .changed => try storage.graph.publishTimed(phases, root, graph, head, limits),        .matched => try storage.graph.publishMatchedTimed(phases, root, graph, head, limits),    };    return .{        .graph = graph,        .stats = stats,        .project = project,        .executable = executable,        .manifest = manifest,        .mode = mode,        .cache_timing = cache_timing,        .publish = publish,        .source_state_ns = source_state_ns,        .graph_load_ns = graph_load_ns,        .scan_ns = scan_ns,    };}fn scanGraph(    allocator: std.mem.Allocator,    phases: std.mem.Allocator,    graph: *graph_mod.Graph,    root: []const u8,    project: ?scanner.scan_files.ProjectState,    executable: ?scanner.scan_files.SourceDigest,    changed_paths: []const []const u8,    mode: ScanMode,    cache_timing: *scanner.CachedProjectTiming,    limits: smg.Limits,) !scanner.Stats {    return switch (mode) {        .full => if (executable != null and project != null) cached: {            const cached = try scanner.scanProjectCached(                allocator,                phases,                graph,                root,                project.?,                executable.?,                limits,            );            cache_timing.* = cached.timing;            break :cached cached.stats;        } else try scanner.scanPathsWithOptions(            allocator,            graph,            root,            &.{},            false,            .{ .limits = limits, .phases = phases },        ),        .changed => if (changed_paths.len == 0)            scanner.Stats{}        else            try scanner.scanPathsWithOptions(                allocator,                graph,                root,                changed_paths,                true,                .{ .limits = limits, .phases = phases },            ),        .matched => scanner.Stats{},    };}fn writeProgress(    allocator: std.mem.Allocator,    mode: ScanMode,    stats: scanner.Stats,    changed_files: usize,    project: ?scanner.scan_files.ProjectState,) !void {    const line = switch (mode) {        .full => try cli_scan.refreshAbsentLine(allocator, stats),        .changed => try cli_scan.refreshChangedLine(allocator, changed_files),        .matched => try cli_scan.refreshMatchedLine(allocator, project.?.project.files),    };    try cli_output.writeErr(line);}fn verifySource(    allocator: std.mem.Allocator,    phases: std.mem.Allocator,    root: []const u8,    refreshed: *RefreshedGraph,    limits: smg.Limits,) !u64 {    const started = sys.time.nanoTimestamp();    const expected = if (refreshed.project) |project| project.project.digest else null;    const verified = if (refreshed.executable != null and expected != null)        scanner.scan_files.projectIdentity(allocator, phases, root, &.{}, limits.scan) catch null    else        null;    if (refreshed.executable != null and expected != null and verified != null and        std.mem.eql(u8, &expected.?, &verified.?.digest))    {        try updateSourceCaches(allocator, phases, root, refreshed, verified.?.digest, limits);    } else if (refreshed.executable != null) {        try cli_output.writeErr("refresh-check: source changed during refresh; next refresh will scan fully\n");    }    return sinceNanoseconds(started);}fn updateSourceCaches(    allocator: std.mem.Allocator,    phases: std.mem.Allocator,    root: []const u8,    refreshed: *RefreshedGraph,    verified: scanner.scan_files.SourceDigest,    limits: smg.Limits,) !void {    if (refreshed.mode == .changed) {        const started = sys.time.nanoTimestamp();        _ = scanner.fragment.writeManifest(            allocator,            phases,            root,            refreshed.executable.?,            refreshed.project.?.project,            &refreshed.manifest,            refreshed.project.?.sources,            limits.scan,        ) catch {            try cli_output.writeErr(                "refresh-check: source snapshot cache unavailable; next change will scan fully\n",            );        };        refreshed.cache_timing.manifest_write_ns += sinceNanoseconds(started);    }    storage.source.writeForHead(        allocator,        root,        refreshed.publish.head,        refreshed.executable.?,        verified,    ) catch try cli_output.writeErr(        "refresh-check: source identity cache unavailable; next refresh will scan fully\n",    );}const Timing = struct {    total_ns: u64,    snapshot_ns: u64,    source_state_ns: u64,    graph_load_ns: u64,    scan_ns: u64,    source_verify_ns: u64,    scan_mode: ScanMode,    cache: scanner.CachedProjectTiming,    publish: storage.graph.PublishTiming,    rule_ns: u64,};fn timingLine(allocator: std.mem.Allocator, timing: Timing) ![]const u8 {    return try std.fmt.allocPrint(        allocator,        "refresh-check timing total_ms={d} snapshot_ms={d} source_state_ms={d} graph_load_ms={d} scan_ms={d} source_verify_ms={d} scan_mode={s} " ++            "fragment_manifest_ms={d} fragment_read_ms={d} fragment_validation_ms={d} fragment_fold_ms={d} fragment_scan_ms={d} " ++            "suffix_index_ms={d} resolution_ms={d} call_metrics_ms={d} fragment_manifest_write_ms={d} " ++            "graph_encode_ms={d} summary_encode_ms={d} index_encode_ms={d} index_mode={s} " ++            "node_puts={d} node_deletes={d} edge_puts={d} edge_deletes={d} " ++            "atomic_publish_ms={d} rule_evaluation_ms={d}\n",        .{            milliseconds(timing.total_ns),            milliseconds(timing.snapshot_ns),            milliseconds(timing.source_state_ns),            milliseconds(timing.graph_load_ns),            milliseconds(timing.scan_ns),            milliseconds(timing.source_verify_ns),            @tagName(timing.scan_mode),            milliseconds(timing.cache.manifest_ns),            milliseconds(timing.cache.fragment_read_ns),            milliseconds(timing.cache.fragment_validation_ns),            milliseconds(timing.cache.fragment_fold_ns),            milliseconds(timing.cache.fragment_scan_ns),            milliseconds(timing.cache.suffix_index_ns),            milliseconds(timing.cache.resolution_ns),            milliseconds(timing.cache.call_metrics_ns),            milliseconds(timing.cache.manifest_write_ns),            milliseconds(timing.publish.graph_ns),            milliseconds(timing.publish.summary_ns),            milliseconds(timing.publish.index_ns),            @tagName(timing.publish.index_kind),            timing.publish.node_puts,            timing.publish.node_deletes,            timing.publish.edge_puts,            timing.publish.edge_deletes,            milliseconds(timing.publish.atomicNanoseconds()),            milliseconds(timing.rule_ns),        },    );}fn elapsedNanoseconds(started: *i128) u64 {    const finished = sys.time.nanoTimestamp();    std.debug.assert(finished >= started.*);    const elapsed: u64 = @intCast(finished - started.*);    started.* = finished;    return elapsed;}fn sinceNanoseconds(started: i128) u64 {    const finished = sys.time.nanoTimestamp();    std.debug.assert(finished >= started);    return @intCast(finished - started);}fn milliseconds(nanoseconds: u64) u64 {    return nanoseconds / std.time.ns_per_ms;}test "refresh timing names complete owner phases" {    const rendered = try timingLine(std.testing.allocator, .{        .total_ns = 36 * std.time.ns_per_ms,        .snapshot_ns = 1 * std.time.ns_per_ms,        .source_state_ns = 2 * std.time.ns_per_ms,        .graph_load_ns = 3 * std.time.ns_per_ms,        .scan_ns = 2 * std.time.ns_per_ms,        .source_verify_ns = 4 * std.time.ns_per_ms,        .scan_mode = .matched,        .cache = .{            .manifest_ns = 5 * std.time.ns_per_ms,            .fragment_read_ns = 6 * std.time.ns_per_ms,            .fragment_validation_ns = 7 * std.time.ns_per_ms,            .fragment_fold_ns = 8 * std.time.ns_per_ms,            .fragment_scan_ns = 9 * std.time.ns_per_ms,            .suffix_index_ns = 10 * std.time.ns_per_ms,            .resolution_ns = 11 * std.time.ns_per_ms,            .call_metrics_ns = 12 * std.time.ns_per_ms,            .manifest_write_ns = 13 * std.time.ns_per_ms,        },        .publish = .{            .head = @splat(0),            .begin_ns = 3 * std.time.ns_per_ms,            .graph_ns = 4 * std.time.ns_per_ms,            .summary_ns = 5 * std.time.ns_per_ms,            .index_ns = 6 * std.time.ns_per_ms,            .index_kind = .incremental,            .node_puts = 9,            .node_deletes = 10,            .edge_puts = 11,            .edge_deletes = 12,            .finish_ns = 7 * std.time.ns_per_ms,        },        .rule_ns = 8 * std.time.ns_per_ms,    });    defer std.testing.allocator.free(rendered);    try std.testing.expectEqualStrings(        "refresh-check timing total_ms=36 snapshot_ms=1 source_state_ms=2 graph_load_ms=3 scan_ms=2 source_verify_ms=4 scan_mode=matched " ++            "fragment_manifest_ms=5 fragment_read_ms=6 fragment_validation_ms=7 fragment_fold_ms=8 fragment_scan_ms=9 " ++            "suffix_index_ms=10 resolution_ms=11 call_metrics_ms=12 fragment_manifest_write_ms=13 " ++            "graph_encode_ms=4 summary_encode_ms=5 index_encode_ms=6 index_mode=incremental " ++            "node_puts=9 node_deletes=10 edge_puts=11 edge_deletes=12 " ++            "atomic_publish_ms=10 rule_evaluation_ms=8\n",        rendered,    );}

Source: tools/smg/src/command/check/root.zig:2

zig
pub const refresh = @import("refresh.zig");

Audit

Definitions2
Public names2
Members0
Version26.7.0
Revisiondaab053ee433