
# Cachelagret AST-søgning

Cachelagret AST-søgning er en supplerende tilstand med opvarmet cache, der bruges sammen med [faktaindekset](https://greph.inline0.dev/da/docs/indexed/ast). I stedet for at gemme udtrukne fakta og parse matchede filer på ny gemmer cachen serialiserede parsetræer på disken. Efterfølgende forespørgsler deserialiserer træerne og kører matcheren direkte, så hele PHP-Parser-forløbet springes over.

Cachen er tilgængelig via underkommandoen `greph-index ast-cache` CLI og facademetoderne `Greph::buildAstCache()` / `Greph::searchAstCached()`. Den understøtter også søgning på tværs af flere indekser og manifestbaserede sæt.

## Oprettelse af cachen

```bash
# Full build at the current directory
./vendor/bin/greph-index ast-cache build .

# Use a non-default cache directory
./vendor/bin/greph-index ast-cache build . --index-dir /tmp/greph-ast-cache

# Build a cache that may refresh automatically for small changes
./vendor/bin/greph-index ast-cache build . \
  --lifecycle opportunistic-refresh \
  --auto-refresh-max-files 32 \
  --auto-refresh-max-bytes 1048576
```

Cachen gemmes som standard på `<root>/.greph-ast-cache/`. Cacheoprettelse er typisk den langsomste af de tre indekstilstande, fordi hver fil skal parses én gang.

En vellykket oprettelse udskriver en oversigt på én linje:

```text
Built AST cache for 2547 files in .greph-ast-cache (2541 cached trees, +2541 ~0 -0 =0)
```

Antallet af cachelagrede træer er som regel lidt lavere end antallet af filer, fordi filer, der ikke kan parses (og derfor springes over uden besked), ikke får en cachepost. Angiv `--strict-parse` i søgekommandoen, hvis parsefejl skal vises.

## Opdatering af cachen

```bash
./vendor/bin/greph-index ast-cache refresh .
```

`refresh` gennemgår den indekserede rod igen, parser ændrede filer på ny og omskriver kun de cachelagrede træer, der er ændret.

Livscyklusprofilerne svarer til profilerne i de andre tilstande med opvarmede indekser:

- `static`: kontrollér aldrig automatisk, om dataene er aktuelle, og foretag aldrig automatiske ændringer
- `manual-refresh`: rapportér forældet tilstand i `stats`, men opdatér aldrig under søgning
- `opportunistic-refresh`: opdatér under søgning, kun når ændringerne holder sig under de konfigurerede grænser
- `strict-stale-check`: afvis forældede søgninger i stedet for at opdatere

## Forespørgsler i cachen

```bash
./vendor/bin/greph-index ast-cache search 'new $CLASS()' src
./vendor/bin/greph-index ast-cache search '$obj->$method($$$ARGS)' src
./vendor/bin/greph-index ast-cache search --json 'array($$$ITEMS)' src
./vendor/bin/greph-index ast-cache search --fallback scan 'new $CLASS()' src
./vendor/bin/greph-index ast-cache search --trace-plan 'array($$$ITEMS)' src
```

Flagene er identiske med dem i [`ast-index search`](https://greph.inline0.dev/da/docs/indexed/ast#querying-the-index), herunder `--fallback scan` til manglende cacher.

### Cache-søgning på tværs af flere indekser

Gentag `--index-dir` for at søge i flere opvarmede cacher i én omgang:

```bash
./vendor/bin/greph-index ast-cache search \
  --index-dir ../wordpress/.greph-ast-cache \
  --index-dir ./.greph-ast-cache \
  --show-index-origin \
  'array($$$ITEMS)' .
```

### Manifestbaserede cachesæt

Hvis du allerede bruger navngivne sæt med opvarmede indekser, kan det samme manifest bruges til cachelagret AST-søgning:

```bash
./vendor/bin/greph-index set build --mode ast-cache
./vendor/bin/greph-index set stats --mode ast-cache --dry-refresh
./vendor/bin/greph-index set search --mode ast-cache --show-index-origin 'array($$$ITEMS)' .
```

### Diagnostik fra planlæggeren

`--trace-plan` rapporterer planlæggerens beslutninger for den cachelagrede AST til `stderr`, herunder:

- hvilke opvarmede cacher der blev søgt i
- om logikken til opdatering af forældede data blev kørt
- antal kandidatfiler efter indsnævring på filniveau
- hvor mange cachelagrede træer der blev deserialiseret til præcis strukturel matching

## Cache kontra faktaindeks

Begge tilstande gør AST-søgning hurtigere, men optimerer til forskellige typer arbejde.

| Aspekt | Faktindeks (`ast-index`) | Cache (`ast-cache`) |
|---|---|---|
| Hvad gemmes | Udtrukne fakta (kaldnavne, klassenavne, deklarationer) | Serialiserede parsede træer |
| Byggeomkostning | Lavere | Højere (parser alt) |
| Størrelse | Mindre | Større |
| Forespørgselsforløb | Filtrér efter fakta, og parse og match derefter kandidaterne | Deserialisér træet, og match derefter |
| Bedst til | Mønstre med et genkendeligt hoved (kaldnavn, klassenavn) | Mønstre, hvis særkende er strukturelt, ikke navnebaseret |
| Dårligst til | Mønstre, hvis hoved er en metavariabel | Kolde forespørgsler på et træ, der ikke længere passer i OS'ets sidecache |

I praksis har faktindekset den hurtigste kolde forespørgsel, mens cachen har den hurtigste varme forespørgsel. Brug den løsning, der passer til din arbejdsbelastning, eller byg begge, og lad dine værktøjer vælge.

## Programmatisk brug

```php
use Greph\Greph;
use Greph\Ast\AstSearchOptions;
use Greph\Index\IndexLifecycleProfile;

Greph::buildAstCache('.', lifecycle: IndexLifecycleProfile::Static);

$matches = Greph::searchAstCached(
    'array($$$ITEMS)',
    'src',
    new AstSearchOptions(jobs: 4, tracePlan: true),
);
```

`searchAstCached` accepterer de samme `AstSearchOptions` som indbygget AST-søgning og returnerer samme `list<AstMatch>`-struktur. Den eneste forskel er, at parserforløbet springes over for filer, der allerede er i cachen. Brug `searchAstCachedMany(...)` og `searchAstCachedSet(...)` til forløb med flere indeks eller manifestunderstøttelse.

## Hvornår skal den bruges

Cached AST-tilstand er det rette værktøj, når:

- Du kører gentagne strukturelle forespørgsler mod den samme kodebase.
- Flaskehalsen i dine tidligere kørsler var PHP-Parser (synligt i profiler som tid brugt i lexer og parser).
- Du har diskplads nok til det serialiserede trælager.

Hvis dine forespørgsler normalt rammer en lille del af kodebasen, og resultaterne samler sig omkring genkendelige kaldnavne eller klassenavne, er [faktindekset](https://greph.inline0.dev/da/docs/indexed/ast) som regel et bedre valg. Hvis dine forespørgsler dækker store dele af kodebasen, men du kan betale engangsomkostningen ved parsing, er cachen bedst.
