Google Cloud¶
On Google Cloud, the bucket is a Cloud Storage bucket, your processes run on Cloud Run, GKE, Compute Engine, or Cloud Functions, and the jobs run as Cloud Run jobs triggered by Cloud Scheduler.
pip install "cairndb[gcs]"
GCS enforces CairnDB’s preconditions natively. Put-if-absent is
if_generation_match=0, and compare-and-swap is if_generation_match
on the object’s current generation, which serves as its etag.
1. Create the bucket¶
gcloud storage buckets create gs://myapp-cairndb \
--location=europe-west1 --uniform-bucket-level-access --public-access-prevention
gcloud storage buckets update gs://myapp-cairndb --soft-delete-duration=7d # or --versioning
2. Grant access¶
Create a service account for your workloads and grant it object access on the bucket:
gcloud iam service-accounts create cairndb
gcloud storage buckets add-iam-policy-binding gs://myapp-cairndb \
--member=serviceAccount:cairndb@<project>.iam.gserviceaccount.com \
--role=roles/storage.objectUser
Attach the service account to your Cloud Run services and jobs, GKE
workloads (Workload Identity), or VMs. CairnDB then authenticates through
Application Default Credentials. Use a key file (credentials_path) only
outside Google Cloud.
3. Configure your application¶
db = CairnDB.configure({"storage": {
"type": "gcs",
"bucket": "myapp-cairndb",
"project": "<project>", # optional
"prefix": "prod", # optional
}})
or, from the environment:
CAIRNDB_STORAGE_TYPE=gcs
CAIRNDB_GCS_BUCKET=myapp-cairndb
CAIRNDB_GCS_PROJECT=<project>
CAIRNDB_STORAGE_PREFIX=prod
# CAIRNDB_GCS_CREDENTIALS_PATH=/path/key.json # only outside Google Cloud
CAIRNDB_S3_BUCKET is also accepted as a fallback for the GCS bucket
when CAIRNDB_GCS_BUCKET is unset.
Cloud Run services¶
Projections live on the instance’s in-memory filesystem. Budget memory for the projection plus one copy during the atomic swap, or mount a volume.
With CPU allocated only during requests, background polling (
proj.start()) stalls between requests. Callawait proj.refresh()in requests that read, or enable always-on CPU.
4. Schedule the jobs¶
Push your jobs image (see The jobs image) to Artifact Registry, and create one Cloud Run job per task:
gcloud artifacts repositories create cairndb --repository-format=docker --location=europe-west1
docker tag myapp-jobs europe-west1-docker.pkg.dev/<project>/cairndb/myapp-jobs:latest
docker push europe-west1-docker.pkg.dev/<project>/cairndb/myapp-jobs:latest
gcloud run jobs create cairndb-snapshot \
--region=europe-west1 \
--image=europe-west1-docker.pkg.dev/<project>/cairndb/myapp-jobs:latest \
--service-account=cairndb@<project>.iam.gserviceaccount.com \
--set-env-vars=CAIRNDB_STORAGE_TYPE=gcs,CAIRNDB_GCS_BUCKET=myapp-cairndb \
--args=snapshot,--handlers,myapp.projections:registry,--init-schema,myapp.projections:init_schema \
--memory=1Gi --task-timeout=30m --max-retries=1
gcloud run jobs create cairndb-gc \
--region=europe-west1 \
--image=europe-west1-docker.pkg.dev/<project>/cairndb/myapp-jobs:latest \
--service-account=cairndb@<project>.iam.gserviceaccount.com \
--set-env-vars=CAIRNDB_STORAGE_TYPE=gcs,CAIRNDB_GCS_BUCKET=myapp-cairndb \
--args=gc,--keep-snapshots,3
Trigger them on a schedule with Cloud Scheduler. The scheduler’s service
account needs roles/run.invoker on the jobs:
gcloud scheduler jobs create http cairndb-snapshot-nightly \
--location=europe-west1 --schedule="0 3 * * *" --time-zone=UTC \
--http-method=POST \
--uri="https://run.googleapis.com/v2/projects/<project>/locations/europe-west1/jobs/cairndb-snapshot:run" \
--oauth-service-account-email=scheduler@<project>.iam.gserviceaccount.com
Create the GC trigger the same way (for example, --schedule="0 4 * * 0").