From a9a384972649182c188396c5f996ae617d35188a Mon Sep 17 00:00:00 2001 From: Martin Kagamino Lehoux Date: Mon, 24 Aug 2026 12:07:30 +0200 Subject: Add progress bars to the long-running CLI processes (backtest, backfill, extract-osm) --- mountain_pass/extract.go | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) (limited to 'mountain_pass/extract.go') diff --git a/mountain_pass/extract.go b/mountain_pass/extract.go index 705dbd3..9643603 100644 --- a/mountain_pass/extract.go +++ b/mountain_pass/extract.go @@ -24,14 +24,28 @@ const insertStatement = ` longitude = excluded.longitude ` -func ExtractMountainPasses(ctx context.Context, pbfPath string, db *sql.DB) (int, error) { +// ExtractMountainPasses scans pbfPath for mountain pass nodes and upserts them +// into the database. An optional reporter is invoked as scanning progresses +// with bytes scanned and the total file size, so callers (e.g. the CLI) can +// render progress. +func ExtractMountainPasses(ctx context.Context, pbfPath string, db *sql.DB, reporters ...func(current, total int64)) (int, error) { file, err := os.Open(pbfPath) if err != nil { return 0, fmt.Errorf("failed to open pbf file: %w", err) } defer file.Close() - scanner := osmpbf.New(ctx, file, 4) + info, err := file.Stat() + if err != nil { + return 0, fmt.Errorf("failed to stat pbf file: %w", err) + } + total := info.Size() + report := func(int64, int64) {} + if len(reporters) > 0 { + report = reporters[0] + } + reader := &countingReader{r: file} + scanner := osmpbf.New(ctx, reader, 4) scanner.SkipWays = true scanner.SkipRelations = true scanner.FilterNode = isMountainPass @@ -50,6 +64,7 @@ func ExtractMountainPasses(ctx context.Context, pbfPath string, db *sql.DB) (int count := 0 for scanner.Scan() { + report(reader.n, total) node, ok := scanner.Object().(*osm.Node) if !ok { continue @@ -74,6 +89,19 @@ func ExtractMountainPasses(ctx context.Context, pbfPath string, db *sql.DB) (int return count, nil } +// countingReader tracks the number of bytes read from an underlying reader, +// used to report scan progress against the PBF file size. +type countingReader struct { + r io.Reader + n int64 +} + +func (c *countingReader) Read(p []byte) (int, error) { + n, err := c.r.Read(p) + c.n += int64(n) + return n, err +} + func isMountainPass(node *osm.Node) bool { if node.Tags.Find("mountain_pass") == "yes" { return true -- cgit v1.3