feat(fire-planner): FIRE Countdown dashboard section + monthly target solve
Some checks failed
ci/woodpecker/push/default Pipeline was canceled
Some checks failed
ci/woodpecker/push/default Pipeline was canceled
Add a "FIRE Countdown" section to the wealth Grafana dashboard plus a monthly CronJob that computes the targets it reads. Viktor wanted a £ countdown to retirement in today's money, per life-case (Solo / Household / Family) and per country, with progress, a projected date, runway, and his safety guardrails — so he can see how close he is to FIRE (ideally lean) without ever coming back to work. - wealth.json: new country / with_home / savings_per_year template vars + a per-Case row (target NW at the 99% GK bar, progress gauge, still-needed, projected FIRE date, runway) and safety-valve panels (re-entry trigger vs £1.0M, 2.5yr cash buffer, pension tranche @57, Anca-bridge note). Reads fire_planner.fire_target via the fire-planner-pg datasource (Mixed). - fire-planner stack: fire-planner-fire-targets CronJob (monthly, 2nd 10:00 UTC) runs `recompute-fire-targets --countries all`. Targets come from the solver shipped in fire-planner edb4d11. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
parent
6ba60cbb2d
commit
08bdf32aa0
2 changed files with 1292 additions and 1 deletions
|
|
@ -459,6 +459,88 @@ resource "kubernetes_cron_job_v1" "fire_planner_recompute" {
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Monthly FIRE-countdown target solve on the 2nd at 10:00 UTC (an hour after
|
||||||
|
# recompute-all, so account_snapshot is fresh). Binary-searches each Case's FIRE
|
||||||
|
# number per country at the 99% Guyton-Klinger bar and upserts fire_target, which
|
||||||
|
# the wealth Grafana dashboard's "FIRE Countdown" section reads.
|
||||||
|
resource "kubernetes_cron_job_v1" "fire_planner_fire_targets" {
|
||||||
|
metadata {
|
||||||
|
name = "fire-planner-fire-targets"
|
||||||
|
namespace = kubernetes_namespace.fire_planner.metadata[0].name
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
schedule = "0 10 2 * *"
|
||||||
|
concurrency_policy = "Forbid"
|
||||||
|
successful_jobs_history_limit = 3
|
||||||
|
failed_jobs_history_limit = 5
|
||||||
|
starting_deadline_seconds = 600
|
||||||
|
|
||||||
|
job_template {
|
||||||
|
metadata {
|
||||||
|
labels = local.labels
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
backoff_limit = 1
|
||||||
|
ttl_seconds_after_finished = 86400
|
||||||
|
# The full country sweep is CPU-bound (binary search × ~22 cities ×
|
||||||
|
# 3 cases). Give it room rather than letting it run forever.
|
||||||
|
active_deadline_seconds = 3600
|
||||||
|
template {
|
||||||
|
metadata {
|
||||||
|
labels = local.labels
|
||||||
|
}
|
||||||
|
spec {
|
||||||
|
restart_policy = "OnFailure"
|
||||||
|
image_pull_secrets {
|
||||||
|
name = "registry-credentials"
|
||||||
|
}
|
||||||
|
image_pull_secrets {
|
||||||
|
name = "ghcr-credentials"
|
||||||
|
}
|
||||||
|
container {
|
||||||
|
name = "fire-targets"
|
||||||
|
image = local.image
|
||||||
|
command = ["python", "-m", "fire_planner", "recompute-fire-targets",
|
||||||
|
"--countries", "all"]
|
||||||
|
|
||||||
|
env_from {
|
||||||
|
secret_ref {
|
||||||
|
name = "fire-planner-secrets"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
env_from {
|
||||||
|
secret_ref {
|
||||||
|
name = "fire-planner-db-creds"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
resources {
|
||||||
|
requests = {
|
||||||
|
cpu = "500m"
|
||||||
|
memory = "1Gi"
|
||||||
|
}
|
||||||
|
limits = {
|
||||||
|
memory = "2Gi"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lifecycle {
|
||||||
|
# KYVERNO_LIFECYCLE_V1
|
||||||
|
ignore_changes = [spec[0].job_template[0].spec[0].template[0].spec[0].dns_config]
|
||||||
|
}
|
||||||
|
|
||||||
|
depends_on = [
|
||||||
|
kubernetes_manifest.external_secret,
|
||||||
|
kubernetes_manifest.db_external_secret,
|
||||||
|
]
|
||||||
|
}
|
||||||
|
|
||||||
# Weekly refresh of the COL cache: walks col_snapshot for rows
|
# Weekly refresh of the COL cache: walks col_snapshot for rows
|
||||||
# expiring within 7 days, re-scrapes Numbeo + Expatistan, upserts. With
|
# expiring within 7 days, re-scrapes Numbeo + Expatistan, upserts. With
|
||||||
# the user-chosen 1-year TTL, a healthy cache has 0 stale rows on most
|
# the user-chosen 1-year TTL, a healthy cache has 0 stale rows on most
|
||||||
|
|
|
||||||
File diff suppressed because it is too large
Load diff
Loading…
Add table
Add a link
Reference in a new issue