library(epwshiftr)
workflow_root <- file.path(tempdir(), "epwshiftr-esg-store")
if (dir.exists(workflow_root)) {
unlink(workflow_root, recursive = TRUE)
}
dir.create(workflow_root, recursive = TRUE, showWarnings = FALSE)
options(
epwshiftr.dir_cache = file.path(workflow_root, "cache")
)
select_cols <- function(x, cols, n = 10L) {
x <- data.table::as.data.table(x)
keep <- intersect(cols, names(x))
if (length(keep)) {
x <- x[, keep, with = FALSE]
}
utils::head(x, n)
}EsgStore is the durable workspace behind the future EPW workflow. The high-level
shift_*() functions carry store paths and manifest IDs for
ordinary workflows, but the lower-level store API is useful when you
need to inspect, update, maintain, or repair a project.
An ESG store has two parts:
Use store methods to change store state. Manual edits to the manifest or moving registered files by hand can break the links that let epwshiftr resume work.
Use a persistent path for real projects. This article uses a temporary path and removes it before each render so the live output is reproducible.
store_path <- file.path(workflow_root, "store")
store <- EsgStore$new(store_path)
store$path
#> [1] "/private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-esg-store/store"
store$manifest
#> [1] "/private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-esg-store/store/manifest.duckdb"
list.files(store$path, all.files = TRUE, no.. = TRUE)
#> [1] "dicts" "downloads" "extracts"
#> [4] "logs" "manifest.duckdb" "manifest.duckdb.wal"
#> [7] "outputs" "queries" "sources"
#> [10] "tmp"EsgStore$new() creates these directories:
queries/: serialized query and result snapshots.dicts/: saved project dictionaries.sources/: raw upstream dictionary or request
sources.downloads/: store-managed NetCDF downloads.extracts/: site-scale extracted Parquet outputs.outputs/: morphing outputs and generated EPW
files.tmp/: temporary working files, including
tmp/downloads/.logs/: downloader background job and daemon logs.The root path and manifest path are not meant to be changed after creation. If you need a new location, create a new store or move the whole store directory as a unit while no R process has it open.
The manifest is a DuckDB database. store$query() is the
safe read path for ad-hoc inspection.
store$query("
SELECT table_name
FROM information_schema.tables
WHERE table_schema = 'main'
ORDER BY table_name
")
#> table_name
#> <char>
#> 1: artifact
#> 2: epw_baseline_summary
#> 3: epw_climate_summary
#> 4: epw_morph_factor
#> 5: epw_morph_plan
#> 6: epw_morph_result
#> 7: epw_output
#> 8: epw_source
#> 9: esg_file
#> 10: esg_query
#> 11: esg_query_dependency
#> 12: esg_query_file
#> 13: esg_query_tag
#> 14: esg_query_update
#> 15: esg_query_update_file
#> 16: extraction_plan
#> 17: extraction_result
#> 18: file_catalog
#> 19: query_run
#> 20: store_meta
#> table_name
#> <char>The core table families are:
store_meta;artifact;esg_query,
esg_query_file, esg_query_update,
esg_query_update_file, esg_query_tag,
esg_query_dependency;esg_file,
file_catalog;extraction_plan,
extraction_result;epw_source,
epw_baseline_summary, epw_climate_summary,
epw_morph_plan, epw_morph_factor,
epw_morph_result, epw_output.Downloader state is stored in the downloader’s own manifest. When you
create it through store$downloader(), that manifest lives
under tmp/downloads/.
store$get_meta("schema_version")
#> [1] "2.2.0"
store$download_layout()
#> $layout
#> [1] "flat"
#>
#> $template
#> NULL
#>
#> $include_version
#> [1] TRUE
#>
#> $collision
#> [1] "error"
#>
#> $missing
#> [1] "fallback"Only the download layout is designed to be changed after store creation. Choose it before large downloads so paths stay stable.
store$set_download_layout(
layout = "drs",
include_version = TRUE,
collision = "error",
missing = "fallback"
)
store$download_layout()
#> $layout
#> [1] "drs"
#>
#> $template
#> NULL
#>
#> $include_version
#> [1] TRUE
#>
#> $collision
#> [1] "error"
#>
#> $missing
#> [1] "fallback"Supported layouts are:
flat: put files directly under
downloads/;dataset: group by ESGF dataset identity;drs: use a CMIP-style DRS path;template: use a custom subdirectory template such as
{source_id}/{experiment_id}/{variable_id}.collision controls what happens when different logical
files map to the same path. missing controls whether
missing layout fields fall back to a safe path or stop the
operation.
add_query() stores a query definition, not just one
collected result. Tracked queries can later be previewed, updated,
tagged, and used to build download plans.
variables <- epw_morph_variables("recommended")
query <- esg_query("https://esgf-data.dkrz.de")$
activity_id("ScenarioMIP")$
experiment_id("ssp585")$
source_id("MPI-ESM1-2-LR")$
variant_label("r1i1p1f1")$
frequency("mon")$
variable_id(variables)$
data_node("esgf.ceda.ac.uk")$
params(table_id = "Amon")$
limit(20L)
query_id <- store$add_query(
query,
label = "singapore-ssp585-amon",
track = TRUE
)
store$tag_query(query_id, c("cmip6", "future-weather", "singapore"))
#> tag_id
#> <char>
#> 1: 90fd88e61cc8ac71279f6c493c5187893509f1d68bd44253b43e8af7719935fa
#> 2: d3995f016f00eabd83ed647a46f22b5478edd220b0b4f6404ad2d53e12f767b6
#> 3: e99dfabf0021b3cbe46813a0018d9984d652141ee0daf895a6a882dc073a0644
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 2: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 3: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> tag created_at
#> <char> <POSc>
#> 1: cmip6 2026-06-24 18:15:15
#> 2: future-weather 2026-06-24 18:15:15
#> 3: singapore 2026-06-24 18:15:15
select_cols(store$queries(), c(
"query_id", "label", "index_node", "tracked", "created_at"
))
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> label index_node tracked created_at
#> <char> <char> <lgcl> <POSc>
#> 1: singapore-ssp585-amon https://esgf-data.dkrz.de TRUE 2026-06-24 18:15:15
store$query_tags(query_id)
#> tag_id
#> <char>
#> 1: 90fd88e61cc8ac71279f6c493c5187893509f1d68bd44253b43e8af7719935fa
#> 2: d3995f016f00eabd83ed647a46f22b5478edd220b0b4f6404ad2d53e12f767b6
#> 3: e99dfabf0021b3cbe46813a0018d9984d652141ee0daf895a6a882dc073a0644
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 2: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 3: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> tag created_at
#> <char> <POSc>
#> 1: cmip6 2026-06-24 18:15:15
#> 2: future-weather 2026-06-24 18:15:15
#> 3: singapore 2026-06-24 18:15:15The query snapshot is written under queries/, while the
query identity and tracking state are recorded in the manifest.
list.files(file.path(store$path, "queries"), recursive = TRUE)
#> [1] "query-013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c.json"
store$query("
SELECT query_id, label, tracked, query_file
FROM esg_query
")
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> label tracked
#> <char> <lgcl>
#> 1: singapore-ssp585-amon TRUE
#> query_file
#> <char>
#> 1: queries/query-013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c.jsonPreviewing asks ESGF for current File records and compares them with the store’s current links. It does not modify the store.
preview <- store$preview_update_queries(
query_id = query_id,
detail = TRUE,
fields = "*",
all = FALSE,
limit = TRUE
)
preview$summary
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> label file_total current_count new_count stale_count
#> <char> <int> <int> <int> <int>
#> 1: singapore-ssp585-amon 20 0 20 0
#> changed_count deprecated_count retracted_count version_changed_count
#> <int> <int> <int> <int>
#> 1: 0 0 0 20
#> bytes_total bytes_new bytes_changed
#> <num> <num> <num>
#> 1: 175082403 175082403 0
select_cols(preview$changes, c(
"change_type", "file_key", "previous_status", "current_status",
"current_version", "data_node_changed", "url_changed"
), n = 12L)
#> change_type
#> <char>
#> 1: new
#> 2: new
#> 3: new
#> 4: new
#> 5: new
#> 6: new
#> 7: new
#> 8: new
#> 9: new
#> 10: new
#> 11: new
#> 12: new
#> file_key
#> <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> previous_status current_status current_version data_node_changed
#> <char> <char> <char> <lgcl>
#> 1: <NA> current 1 TRUE
#> 2: <NA> current 1 TRUE
#> 3: <NA> current 1 TRUE
#> 4: <NA> current 1 TRUE
#> 5: <NA> current 1 TRUE
#> 6: <NA> current 1 TRUE
#> 7: <NA> current 1 TRUE
#> 8: <NA> current 1 TRUE
#> 9: <NA> current 1 TRUE
#> 10: <NA> current 1 TRUE
#> 11: <NA> current 1 TRUE
#> 12: <NA> current 1 TRUE
#> url_changed
#> <lgcl>
#> 1: TRUE
#> 2: TRUE
#> 3: TRUE
#> 4: TRUE
#> 5: TRUE
#> 6: TRUE
#> 7: TRUE
#> 8: TRUE
#> 9: TRUE
#> 10: TRUE
#> 11: TRUE
#> 12: TRUEUpdating writes the current File identities, file metadata, query-file links, and an update record.
updated <- store$update_queries(
query_id = query_id,
fields = "*",
all = FALSE,
limit = TRUE
)
select_cols(updated, c(
"query_id", "update_id", "status", "file_total",
"new_count", "changed_count", "stale_count"
))
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 2: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 3: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 4: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 5: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 6: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 7: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 8: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 9: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 10: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> update_id status
#> <char> <char>
#> 1: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 2: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 3: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 4: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 5: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 6: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 7: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 8: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 9: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
#> 10: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a current
select_cols(store$query_files(query_id), c(
"query_id", "file_key", "status", "filename", "variable_id",
"data_node", "datetime_start", "datetime_end"
), n = 12L)
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 2: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 3: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 4: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 5: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 6: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 7: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 8: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 9: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 10: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 11: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 12: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> file_key
#> <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> status filename
#> <char> <char>
#> 1: current clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: current clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: current clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: current clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: current clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: current hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: current hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: current hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: current hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: current hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: current psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: current psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> variable_id data_node datetime_start datetime_end
#> <char> <char> <POSc> <POSc>
#> 1: clt esgf.ceda.ac.uk <NA> <NA>
#> 2: clt esgf.ceda.ac.uk <NA> <NA>
#> 3: clt esgf.ceda.ac.uk <NA> <NA>
#> 4: clt esgf.ceda.ac.uk <NA> <NA>
#> 5: clt esgf.ceda.ac.uk <NA> <NA>
#> 6: hurs esgf.ceda.ac.uk <NA> <NA>
#> 7: hurs esgf.ceda.ac.uk <NA> <NA>
#> 8: hurs esgf.ceda.ac.uk <NA> <NA>
#> 9: hurs esgf.ceda.ac.uk <NA> <NA>
#> 10: hurs esgf.ceda.ac.uk <NA> <NA>
#> 11: psl esgf.ceda.ac.uk <NA> <NA>
#> 12: psl esgf.ceda.ac.uk <NA> <NA>query_updates() and query_changes() make
update history reviewable.
updates <- store$query_updates(query_id)
select_cols(updates, c(
"update_id", "query_id", "status", "file_total",
"new_count", "changed_count", "completed_at"
))
#> update_id
#> <char>
#> 1: a05379ab2febbbf61b3f0c1b16cca9cae1e287bdf18225f12352804243132a6a
#> query_id status
#> <char> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c done
#> file_total new_count changed_count completed_at
#> <int> <int> <int> <POSc>
#> 1: 20 20 0 2026-06-24 18:15:20
latest_update <- store$query_updates(query_id, latest = TRUE)
select_cols(
store$query_changes(update_id = latest_update$update_id),
c("change_type", "file_key", "current_status", "current_version"),
n = 12L
)
#> change_type
#> <char>
#> 1: new
#> 2: new
#> 3: new
#> 4: new
#> 5: new
#> 6: new
#> 7: new
#> 8: new
#> 9: new
#> 10: new
#> 11: new
#> 12: new
#> file_key
#> <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> current_status current_version
#> <char> <char>
#> 1: current 1
#> 2: current 1
#> 3: current 1
#> 4: current 1
#> 5: current 1
#> 6: current 1
#> 7: current 1
#> 8: current 1
#> 9: current 1
#> 10: current 1
#> 11: current 1
#> 12: current 1The store owns downloader paths for store-managed downloads. Prefer
store$downloader() so completed tasks can be synchronized
back into esg_file, file_catalog, and
artifact.
downloader <- store$downloader(
n_workers = 2L,
retries = 1L,
timeout = 120L,
resource_policy = list(min_free_space = 0)
)
download_preview <- store$download_preflight(
query_id = query_id,
downloader = downloader,
replica = "current",
service = "HTTPServer",
probe = FALSE,
fields = "*",
all = FALSE,
limit = TRUE
)
download_preview$summary
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> label file_total current_count candidate_count bytes_total
#> <char> <int> <int> <int> <num>
#> 1: singapore-ssp585-amon 20 20 20 175082403
#> local_available needs_download no_httpserver cooldown_nodes
#> <int> <int> <int> <int>
#> 1: 0 20 0 0
#> target_path_collision_count missing_layout_field_count required_bytes
#> <int> <int> <num>
#> 1: 0 0 175082403
#> size_unknown_count dest_free_bytes tmp_free_bytes min_free_space disk_ok
#> <int> <num> <num> <num> <lgcl>
#> 1: 0 298175320064 298175320064 0 TRUE
#> disk_would_block disk_preflight
#> <lgcl> <lgcl>
#> 1: FALSE TRUE
select_cols(download_preview$files, c(
"file_key", "filename", "variable_id", "size",
"local_path", "status"
), n = 12L)
#> file_key
#> <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> filename variable_id
#> <char> <char>
#> 1: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc clt
#> 2: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc clt
#> 3: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc clt
#> 4: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc clt
#> 5: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc clt
#> 6: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc hurs
#> 7: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc hurs
#> 8: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc hurs
#> 9: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc hurs
#> 10: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc hurs
#> 11: psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc psl
#> 12: psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc psl
#> size local_path status
#> <num> <char> <char>
#> 1: 12221286 <NA> current
#> 2: 12227997 <NA> current
#> 3: 12218908 <NA> current
#> 4: 12214277 <NA> current
#> 5: 3703067 <NA> current
#> 6: 11108043 <NA> current
#> 7: 11102939 <NA> current
#> 8: 11096358 <NA> current
#> 9: 11086273 <NA> current
#> 10: 3371769 <NA> current
#> 11: 8245782 <NA> current
#> 12: 8249107 <NA> current
select_cols(download_preview$candidates, c(
"filename", "service", "data_node", "size", "url"
), n = 12L)
#> filename service
#> <char> <char>
#> 1: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc HTTPServer
#> 2: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc HTTPServer
#> 3: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc HTTPServer
#> 4: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc HTTPServer
#> 5: clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc HTTPServer
#> 6: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc HTTPServer
#> 7: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc HTTPServer
#> 8: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc HTTPServer
#> 9: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc HTTPServer
#> 10: hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc HTTPServer
#> 11: psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc HTTPServer
#> 12: psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc HTTPServer
#> data_node size
#> <char> <num>
#> 1: esgf.ceda.ac.uk 12221286
#> 2: esgf.ceda.ac.uk 12227997
#> 3: esgf.ceda.ac.uk 12218908
#> 4: esgf.ceda.ac.uk 12214277
#> 5: esgf.ceda.ac.uk 3703067
#> 6: esgf.ceda.ac.uk 11108043
#> 7: esgf.ceda.ac.uk 11102939
#> 8: esgf.ceda.ac.uk 11096358
#> 9: esgf.ceda.ac.uk 11086273
#> 10: esgf.ceda.ac.uk 3371769
#> 11: esgf.ceda.ac.uk 8245782
#> 12: esgf.ceda.ac.uk 8249107
#> url
#> <char>
#> 1: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/clt/gn/v20190710/clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/clt/gn/v20190710/clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/clt/gn/v20190710/clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/clt/gn/v20190710/clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/clt/gn/v20190710/clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/hurs/gn/v20190815/hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/hurs/gn/v20190815/hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/hurs/gn/v20190815/hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/hurs/gn/v20190815/hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/hurs/gn/v20190815/hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/psl/gn/v20190710/psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: https://esgf.ceda.ac.uk/thredds/fileServer/esg_cmip6/CMIP6/ScenarioMIP/MPI-M/MPI-ESM1-2-LR/ssp585/r1i1p1f1/Amon/psl/gn/v20190710/psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.ncTo enqueue or run downloads, use download_query() or
download_files(). This article stops at preflight because
CMIP NetCDF files are large.
session_id <- store$download_query(
query_id = query_id,
downloader = downloader,
replica = "current",
service = "HTTPServer",
run = TRUE,
progress = TRUE
)
store$sync_downloads(downloader)Extraction plans connect query files to a site, time range,
variables, and a grid method. Planning is metadata-only; extraction
reads OPeNDAP or local NetCDF data and writes Parquet outputs under
extracts/.
region <- store$plan_region(
query_id = query_id,
lon = 103.98,
lat = 1.37,
time = c("2060-01-01T00:00:00Z", "2060-12-31T23:59:59Z"),
site_id = "SIN",
variable_id = variables,
method = "nearest"
)
select_cols(region, c(
"plan_id", "query_id", "file_key", "site_id", "variable_id",
"lon", "lat", "time_start", "time_stop", "status"
), n = 12L)
#> plan_id
#> <char>
#> 1: d4b50b7d552817c501600ca65f64fcc60a548546e4ad2d828b20b1e3021741a1
#> 2: 715b1a8cec66779da8d546715ab6e824517da364158b4b2a2c69752723200139
#> 3: d442dc702cdbdbb9df13f618bef50a49fe8cbdb6391357d637cbbfcc4e1d02ad
#> 4: 0a263f5d9db5417a3fe9314f1ae0dee679884eb562f1076a20b07270ddb58335
#> 5: 40f27b3b430cec3c0d7cacb05dd1c54d1fcc6835e235a14331959a67579861d6
#> 6: 522ddd2e6fa8cf79406dcf023abf420c723c56f4f654542a6ed82a279db6ded1
#> 7: a34f33ffaceef15381cdcff4fd36b0e3dd6a6d4791a47da3ccec1f64c5c087bc
#> 8: d8f84ee054ee73ba2c20a6bbcd155510eea876556d4c1a08a1324d496b72b7ab
#> 9: da20cf96521b8dd55b458d12ceb1e23f14ad1e62bd21e7c754d534543dd31bb1
#> 10: a225a8f9ccade673e8c185121f9ae9899a620715d918cb940481ca340b78c6ee
#> 11: f34dfebd56e7a029ad5a526c787f8efe49e464b85f8107262ddffd301742be4f
#> 12: ba680e4ecadb371e20ad67a8e60770e9ca89795323f44bb0ffc4bf3d438c9599
#> query_id
#> <char>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 2: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 3: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 4: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 5: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 6: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 7: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 8: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 9: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 10: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 11: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> 12: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> file_key
#> <char>
#> 1: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 2: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 3: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 4: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 5: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.clt.gn.clt_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 6: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 7: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> 8: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_205501-207412.nc
#> 9: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_207501-209412.nc
#> 10: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.hurs.gn.hurs_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_209501-210012.nc
#> 11: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_201501-203412.nc
#> 12: master:CMIP6.ScenarioMIP.MPI-M.MPI-ESM1-2-LR.ssp585.r1i1p1f1.Amon.psl.gn.psl_Amon_MPI-ESM1-2-LR_ssp585_r1i1p1f1_gn_203501-205412.nc
#> site_id variable_id lon lat time_start time_stop status
#> <char> <char> <num> <num> <POSc> <POSc> <char>
#> 1: SIN clt 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 2: SIN clt 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 3: SIN clt 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 4: SIN clt 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 5: SIN clt 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 6: SIN hurs 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 7: SIN hurs 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 8: SIN hurs 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 9: SIN hurs 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 10: SIN hurs 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 11: SIN psl 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
#> 12: SIN psl 103.98 1.37 2060-01-01 2060-12-31 23:59:59 pending
select_cols(store$coverage(plan_id = region$plan_id), c(
"plan_id", "site_id", "variable_id", "status",
"complete", "output_rows", "output_time_count"
), n = 12L)
#> Key: <plan_id>
#> plan_id site_id
#> <char> <char>
#> 1: 0529c672b2743d596b4ce567f20bc7da8679879d78416f84bbfa6a1c9d833bb3 SIN
#> 2: 0a263f5d9db5417a3fe9314f1ae0dee679884eb562f1076a20b07270ddb58335 SIN
#> 3: 0ca43af5a197ef5976f6352dfd22e56dcaf56c426d73d32880f0041f5564c131 SIN
#> 4: 40f27b3b430cec3c0d7cacb05dd1c54d1fcc6835e235a14331959a67579861d6 SIN
#> 5: 522ddd2e6fa8cf79406dcf023abf420c723c56f4f654542a6ed82a279db6ded1 SIN
#> 6: 53c9ac1d43c5aff19881432f5380a5d10dba8fb0952df8fd7f30a7d027ad0922 SIN
#> 7: 715b1a8cec66779da8d546715ab6e824517da364158b4b2a2c69752723200139 SIN
#> 8: a225a8f9ccade673e8c185121f9ae9899a620715d918cb940481ca340b78c6ee SIN
#> 9: a34f33ffaceef15381cdcff4fd36b0e3dd6a6d4791a47da3ccec1f64c5c087bc SIN
#> 10: ba680e4ecadb371e20ad67a8e60770e9ca89795323f44bb0ffc4bf3d438c9599 SIN
#> 11: c5335281c01d7170c990eefa1a330328b3c771fd93589ceacb75df7da5c3f8c2 SIN
#> 12: c7e04cbed64b8eb7273d603c4db731e2779b3bb7b7db4e80a54a76ce77914b6d SIN
#> variable_id status complete output_rows output_time_count
#> <char> <char> <lgcl> <int> <int>
#> 1: rlds pending FALSE 0 0
#> 2: clt pending FALSE 0 0
#> 3: psl pending FALSE 0 0
#> 4: clt pending FALSE 0 0
#> 5: hurs pending FALSE 0 0
#> 6: psl pending FALSE 0 0
#> 7: clt pending FALSE 0 0
#> 8: hurs pending FALSE 0 0
#> 9: hurs pending FALSE 0 0
#> 10: psl pending FALSE 0 0
#> 11: rlds pending FALSE 0 0
#> 12: rlds pending FALSE 0 0Use store$extract() when you want to execute the plan.
With fallback = "auto", extraction tries OPeNDAP first and
may fall back to local or HTTP downloads when needed.
Artifacts connect files on disk to manifest records. Query snapshots, dictionaries, NetCDF downloads, extracted Parquet files, morphing intermediates, and EPW outputs all use the same artifact table.
store$validate()
#> artifact_id kind
#> <char> <char>
#> 1: 0ba5c9b45f6e79375ad1cf96f9b5e6409123f14c07ea6552b4a10a1082cacdf4 query
#> expected_path
#> <char>
#> 1: /private/var/folders/8f/t8sk2pps6135xbp47cs8qb2r0000gn/T/Rtmp3Hed7X/epwshiftr-esg-store/store/queries/query-013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c.json
#> exists checksum_ok size_ok status
#> <lgcl> <lgcl> <lgcl> <char>
#> 1: TRUE TRUE TRUE available
store$query("
SELECT kind, role, project, relative_path, status, query_id, file_key
FROM artifact
ORDER BY kind, relative_path
")
#> kind role project
#> <char> <char> <char>
#> 1: query input CMIP6
#> relative_path
#> <char>
#> 1: queries/query-013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c.json
#> status query_id
#> <char> <char>
#> 1: available 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c
#> file_key
#> <char>
#> 1: <NA>When you have an artifact_id, use
artifact_path() to resolve the absolute path instead of
assembling paths by hand.
Maintenance methods are intentionally preview-first. Use validation and dry-run cleanup before changing anything.
report <- store$storage_report(detail = TRUE)
report$summary
#> download_file_count download_bytes registered_file_count registered_bytes
#> <int> <num> <int> <num>
#> 1: 0 0 0 0
#> tmp_file_count tmp_bytes untracked_file_count untracked_bytes
#> <int> <num> <int> <num>
#> 1: 0 0 0 0
#> missing_record_count orphan_record_count
#> <int> <int>
#> 1: 0 0
select_cols(report$downloads, c("relative_path", "size", "mtime"), n = 8L)
#> Empty data.table (0 rows and 3 cols): relative_path,size,mtime
select_cols(report$registered, c("source", "file_key", "relative_path", "size"), n = 8L)
#> Empty data.table (0 rows and 4 cols): source,file_key,relative_path,size
validation <- store$validate_files(
query_id = query_id,
checksum = FALSE,
layout = TRUE
)
validation$summary
#> query_id file_count
#> <char> <int>
#> 1: 013ab6378cd53b86049fed1e762eb4f1338bc3f641e7b3ecb26d5ac0d533c37c 20
#> registered_file_count existing_file_count missing_file_count bad_size_count
#> <int> <int> <int> <int>
#> 1: 0 0 0 0
#> bad_checksum_count artifact_mismatch_count layout_mismatch_count
#> <int> <int> <int>
#> 1: 0 0 0
#> untracked_file_count action_count
#> <int> <int>
#> 1: 0 0
select_cols(validation$actions, c(
"action", "file_key", "artifact_id", "from_path", "to_path", "reason"
), n = 10L)
#> Empty data.table (0 rows and 6 cols): action,file_key,artifact_id,from_path,to_path,reason
store$repair_files(validation$actions, dry_run = TRUE)
#> Empty data.table (0 rows and 10 cols): action_id,action,file_key,artifact_id,from_path,to_path...
store$cleanup_downloads(
scope = "tmp",
older_than = 7 * 24 * 3600,
dry_run = TRUE
)
#> Empty data.table (0 rows and 10 cols): scope,action,path,relative_path,file_key,artifact_id...Checksum validation is useful, but it must read files and can be expensive on a large store. Layout validation is cheaper and catches many broken local-path or artifact-record problems.
shift_*() for the normal end-to-end future EPW
workflow.EsgQuery when you need to understand live
Dataset/File/Aggregation results before they enter a store.EsgStore when you need durable state, query
tracking, file catalog inspection, extraction planning, artifact
validation, or maintenance.Downloader when you need transfer execution
details: sessions, tasks, retries, background jobs, daemon mode, and
node history.EpwMorpher when you need lower-level control over
climate summaries, morphing factors, diagnostics, and EPW writing.