---
title: "Caching strategy and reruns"
output: rmarkdown::html_vignette
vignette: >
  %\VignetteIndexEntry{Caching strategy and reruns}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r, include = FALSE}
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>"
)
```

```{r setup}
library(nlmixr2targets)
```

# What triggers a re-fit?

`nlmixr2targets` builds on `targets`, which caches every target keyed by a
hash of its command, its dependencies, and its inputs. When you call
`tar_make()`, only targets whose hash has changed (directly or
transitively) are rebuilt.

For a single `tar_nlmixr(name = <name>, ...)` call, the four targets
generated are:

| Target | Stores | Hashed inputs |
| ------ | ------ | ------------- |
| `<name>_object_simple` | md5 string identifying the simplified ui in the indirect cache | the captured `object` expression |
| `<name>_data_simple` | simplified data frame | `<name>_object_simple`, the captured `data` expression, the `table$keep` columns |
| `<name>_fit_simple` | fitted nlmixr2 object | `<name>_object_simple`, `<name>_data_simple`, `est`, `control` |
| `<name>` | final fit, with labels and metadata restored | `<name>_fit_simple`, the captured `object` (re-read for labels), `data` |

The single most important property of this layout is that
`<name>_fit_simple` depends only on the **structural** content of the
model. `nlmixr_object_simplify()` strips parameter labels and the model's
metadata environment before caching, so cosmetic edits to either do not
invalidate the expensive estimation step.

# Examples of common edits

```{r examples-of-edits, eval = FALSE}
# Adding a comment, changing a label, or editing meta:
#   only re-runs the cheap `_object_simple` and the final `<name>` target
#   (the relabel/meta-restore step). The expensive `_fit_simple` is reused.

# Changing initial values (`ini({...})`) or the model structure
# (`model({...})`):
#   re-runs everything from `_object_simple` onward.

# Adding/removing a covariate column from the dataset:
#   re-runs `_data_simple` and `_fit_simple`. `_object_simple` is reused
#   if the model didn't change.

# Changing `est` or `control`:
#   re-runs `_fit_simple` and the final target. `_object_simple` and
#   `_data_simple` are reused.
```

# Inspecting and pruning the indirect cache

The simplified-model md5 cache lives under
`<tar_config_get("store")>/user/nlmixr2/`. It is **not** removed by
`targets::tar_destroy()`, so it can accumulate orphan files over time
(e.g. after model iterations).

```{r cache-helpers, eval = FALSE}
# Quick inventory: hashes, sizes, last-modified
nlmixr2targets_cache_status()
#>      hash size_bytes               mtime
#> 1 aaaaaa..       1234 2026-05-21 12:00:00
#> 2 bbbbbb..       1567 2026-05-21 13:30:00

# Find orphans (dry run by default)
nlmixr2targets_cache_prune()

# Delete them
nlmixr2targets_cache_prune(dry_run = FALSE)
```

`nlmixr2targets_cache_prune()` with no `keep` argument reads
`targets::tar_meta()` from the current store, finds every built target
whose name ends in `_object_simple`, and treats those hash values as
reachable. Anything else in the cache directory is reported (and, with
`dry_run = FALSE`, removed). Pass `keep = character()` to wipe the cache
unconditionally.

# `tar_outdated()` is a quick way to preview what would rerun

If you are about to edit a model and are unsure how invasive the change
is, run

```{r tar-outdated, eval = FALSE}
targets::tar_outdated()
```

after the edit but before `tar_make()`. The list of outdated targets is
exactly the set that would re-execute. Three or four entries means
`_fit_simple` is in play; one or two usually means only the cheap
relabel/restore step is.
