Skip to content

feat(cliproxyapi): persist usage-export across restarts via R2 - #1577

Merged
shunkakinoki merged 1 commit into
mainfrom
feat/cliproxyapi-usage-r2-persist
Apr 25, 2026
Merged

feat(cliproxyapi): persist usage-export across restarts via R2#1577
shunkakinoki merged 1 commit into
mainfrom
feat/cliproxyapi-usage-r2-persist

Conversation

@shunkakinoki

@shunkakinoki shunkakinoki commented Apr 25, 2026

Copy link
Copy Markdown
Owner

Summary

  • Add cliproxy_upload_usage_to_s3 and cliproxy_download_usage_from_s3 helpers in common.sh, plus a fixed-key cliproxy_usage_s3_uri (s3://$OBJECTSTORE_BUCKET/usage-export.json).
  • On shutdown, start.sh's existing usage_export trap now uploads ~/.cli-proxy-api/usage-export.json to R2 right after the management API export.
  • On startup, hydrate usage-export.json from R2 only if it's missing locally, so the post-boot usage_import can replay stats on a fresh machine.

Test plan

  • make switch applies cleanly on macOS
  • Stop cliproxyapi (launchctl kickstart -k gui/$(id -u)/org.nixos.cliproxyapi) and confirm s3://cliproxyapi/usage-export.json updates
  • Delete ~/.cli-proxy-api/usage-export.json, restart, confirm it gets pulled from R2 and /v0/management/usage/export returns prior counters

Summary by cubic

Persist usage metrics across restarts by storing usage-export.json in Cloudflare R2 (S3-compatible). On shutdown we upload the export; on startup we hydrate it if missing so usage replay works on fresh machines.

  • New Features
    • Added helpers: cliproxy_upload_usage_to_s3, cliproxy_download_usage_from_s3, and a fixed S3 URI for usage-export.json.
    • On shutdown, upload ~/.cli-proxy-api/usage-export.json right after the management API export.
    • On startup, if the file is missing, download it from R2 before running usage import.

Written for commit 2f44fc7. Summary will update on new commits.

@mesa-dot-dev

mesa-dot-dev Bot commented Apr 25, 2026

Copy link
Copy Markdown

You do not have enough credits to review this pull request. Please purchase more credits to continue.

@coderabbitai

coderabbitai Bot commented Apr 25, 2026

Copy link
Copy Markdown

Caution

Review failed

Pull request was closed or merged during review

📝 Walkthrough

Summary by CodeRabbit

  • New Features
    • Added automated cloud storage integration for usage data. Usage exports are now automatically synchronized from cloud storage on startup and persisted back after each generation, enabling seamless backup and recovery of usage metrics.

Walkthrough

Two shell script files are modified to add S3 persistence capabilities to the cliproxyapi service. Three new helper functions are added to construct S3 URIs and perform conditional uploads/downloads of usage export files. The startup script is updated to hydrate the usage export from S3 on initialization and persist it back to S3 after successful exports.

Changes

Cohort / File(s) Summary
S3 Helper Functions
home-manager/services/cliproxyapi/scripts/common.sh
Three new functions introduced: cliproxy_usage_s3_uri() constructs the target S3 path, cliproxy_upload_usage_to_s3(src) conditionally uploads files when credentials exist, and cliproxy_download_usage_from_s3(dst) downloads usage exports from S3 with error tolerance.
S3 Integration in Startup
home-manager/services/cliproxyapi/scripts/start.sh
Modified to hydrate USAGE_EXPORT_FILE from S3 before startup if credentials are configured, and to persist the file back to S3 after successful usage export requests.

Sequence Diagram

sequenceDiagram
    participant Startup as start.sh
    participant FS as File System
    participant S3 as Object Store (S3)
    participant Export as Export Process
    
    Startup->>Startup: Check for S3 credentials
    alt Credentials Present
        Startup->>S3: Request USAGE_EXPORT_FILE
        alt File Exists in S3
            S3-->>FS: Download to local path
        end
    end
    Startup->>Export: Execute export request
    Export->>FS: Generate usage-export.json
    Export-->>Startup: Export complete
    alt Credentials Present
        Startup->>FS: Read USAGE_EXPORT_FILE
        Startup->>S3: Upload to object store
        S3-->>Startup: Upload acknowledged
    end
Loading

Estimated code review effort

🎯 2 (Simple) | ⏱️ ~10 minutes

Possibly related PRs

Poem

🐰 A rabbit's ode to object stores:

S3 buckets hold our secrets tight,
Downloads hydrate, uploads ignite,
Upload and fetch with grace sublime,
Persistence whispers, byte by byte! 📦✨

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 16.67% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately summarizes the main change: adding persistence of usage metrics across restarts via R2 storage.
Description check ✅ Passed The description is well-detailed and directly related to the changeset, explaining the new helpers, shutdown behavior, and startup hydration logic.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/cliproxyapi-usage-r2-persist

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@mesa-dot-dev

mesa-dot-dev Bot commented Apr 25, 2026

Copy link
Copy Markdown

Mesa Description

TL;DR

Persist cliproxyapi usage-export across restarts by uploading to and downloading from R2, ensuring usage statistics are replayed on fresh machines.

What changed?

  • Added cliproxy_upload_usage_to_s3 and cliproxy_download_usage_from_s3 helpers in common.sh.
  • Defined a fixed S3 URI (s3://$OBJECTSTORE_BUCKET/usage-export.json) for usage exports.
  • Modified start.sh to upload ~/.cli-proxy-api/usage-export.json to R2 on shutdown.
  • Implemented logic in start.sh to hydrate usage-export.json from R2 on startup if it's missing locally.

Description generated by Mesa. Update settings

@shunkakinoki
shunkakinoki merged commit b4d4d87 into main Apr 25, 2026
32 of 33 checks passed
@shunkakinoki
shunkakinoki deleted the feat/cliproxyapi-usage-r2-persist branch April 25, 2026 23:14

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

This pull request implements S3-based persistence for usage export data by adding upload and download utilities to the common script and integrating them into the startup and export processes. The review feedback recommends using shell parameter expansion for mandatory environment variables to ensure better error reporting and consistency with existing patterns.

Comment on lines +70 to +73
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 cp \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with cliproxy_s3_sync and to provide better error reporting if variables are unexpectedly empty, consider using the ${VAR:?} expansion syntax for credentials and the endpoint.

Suggested change
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 cp \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY:?OBJECTSTORE_ACCESS_KEY is required}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY:?OBJECTSTORE_SECRET_KEY is required}" \
@aws@ s3 cp \
--endpoint-url="${OBJECTSTORE_ENDPOINT:?OBJECTSTORE_ENDPOINT is required}" \
References
  1. Maintain consistency with established patterns for writing scripts that are extracted from Nix expressions.

Comment on lines +83 to +86
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 cp \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

medium

For consistency with cliproxy_s3_sync and to provide better error reporting if variables are unexpectedly empty, consider using the ${VAR:?} expansion syntax for credentials and the endpoint.

Suggested change
AWS_ACCESS_KEY_ID="$OBJECTSTORE_ACCESS_KEY" \
AWS_SECRET_ACCESS_KEY="$OBJECTSTORE_SECRET_KEY" \
@aws@ s3 cp \
--endpoint-url="$OBJECTSTORE_ENDPOINT" \
AWS_ACCESS_KEY_ID="${OBJECTSTORE_ACCESS_KEY:?OBJECTSTORE_ACCESS_KEY is required}" \
AWS_SECRET_ACCESS_KEY="${OBJECTSTORE_SECRET_KEY:?OBJECTSTORE_SECRET_KEY is required}" \
@aws@ s3 cp \
--endpoint-url="${OBJECTSTORE_ENDPOINT:?OBJECTSTORE_ENDPOINT is required}" \
References
  1. Maintain consistency with established patterns for writing scripts that are extracted from Nix expressions.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant