D

Data cleanup

Fixtures & lifecycle available

Run cleanup commands on stop() to reset state after a run.

Install
$ loadr plugin install data-cleanup
examples/plugins/data-cleanup.yaml
# Reset a shared environment after a run, driven by the
# `loadr-plugin-data-cleanup` native SERVICE plugin.
#
# Unlike a protocol plugin (which handles requests to a URL scheme), a service
# plugin has a start/stop lifecycle: loadr calls `start(config)` once before the
# run and `stop()` once after. On start this plugin validates the cleanup
# `strategy` (and, for `sql`, opens the pool), then binds a tiny local line
# endpoint and returns its address, e.g.:
#
#   → data-cleanup tracking endpoint at 127.0.0.1:41881
#
# During the run every VU WRITES the id (or absolute URL) of a resource it just
# created to that endpoint — a cheap in-memory push, no per-request network
# cost. Nothing is deleted while the run is hot. When the last VU retires and
# `stop()` runs, the service walks the registry and fires one cleanup call per
# resource: `DELETE <base>/<id>` (http-delete) or a parameterised
# `DELETE FROM <table> WHERE <key> = $1` (sql). A 404 counts as success (the
# resource is already gone), so the environment is returned to its pre-run state
# without a hand-written teardown script.
#
# Build + install the plugin, then run:
#   cargo build -p loadr-plugin-data-cleanup --release
#   mkdir -p dist && cp plugins/loadr-plugin-data-cleanup/plugin.toml dist/ \
#     && cp target/release/libloadr_plugin_data_cleanup.so dist/
#   loadr plugin install dist
#   API_TOKEN=... loadr run examples/plugins/data-cleanup.yaml
#
# Or point the plan's `plugins:` entry at the built artifact directly (below).
name: data-cleanup
description: Delete the resources a run creates once the run ends

plugins:
  # Resolve `data-cleanup` by name from the plugins dir (after
  # `loadr plugin install`). To run straight from a build tree instead, set:
  #   path: target/release/libloadr_plugin_data_cleanup.so
  - name: data-cleanup
    config:
      # "http-delete" issues HTTP DELETEs; "sql" issues parameterised SQL
      # DELETEs. An unknown value fails start() so the plan is rejected up front.
      strategy: http-delete
      # Base URL a tracked id is appended to: id `42` -> DELETE <base>/42. A
      # tracked value that is itself an absolute http(s):// URL is deleted as-is.
      base: https://api.staging.example.com/v1/orders
      # Headers attached to every DELETE — keep secrets in ${env.…}.
      headers:
        Authorization: "Bearer ${env.API_TOKEN}"
      # How many DELETEs run in parallel from stop().
      concurrency: 8
      # Keep deleting the rest when one delete fails; failures are still counted.
      continue_on_error: true
      # Local address the tracking endpoint binds to. Port 0 = ephemeral; the
      # bound address is printed when the run starts.
      bind: 127.0.0.1:0
      # --- SQL strategy (swap the block above for this) ---
      # strategy: sql
      # url: postgres://loadtest@db.staging.example.com/app   # ${env.…} in practice
      # table: orders
      # key: id                                               # DELETE FROM orders WHERE id = $1

defaults:
  http:
    base_url: https://api.staging.example.com

scenarios:
  # Each VU creates an order, then registers the new id with the cleanup service
  # by writing it to the tracking endpoint. Everything created here is torn down
  # by the plugin's stop() at the end of the run.
  create_orders:
    executor: constant-vus
    vus: 25
    duration: 30s
    flow:
      - request:
          name: create order
          method: POST
          url: /v1/orders
          headers:
            Content-Type: application/json
          body: '{"sku":"widget","qty":1}'
          checks:
            - { type: status, equals: 201 }
          # Capture the new id for the tracking step.
          capture:
            - { json: id, as: order_id }
      - request:
          name: track created order
          # Replace with the printed tracking-endpoint address, or wire this in
          # from a hook. One id per line; the service buffers it for teardown.
          url: tcp://127.0.0.1:0
          socket:
            send_text: "${order_id}\n"
            read_bytes: 8
            read_timeout: 2s

thresholds:
  http_req_failed: [ "rate<0.01" ]
  checks: [ "rate>0.99" ]

A real run: install from the signed index, then watch the plugin work.

A runtime plugin, never in the binary

Installing pulls a per-platform driver from the signed index, verifies its SHA-256 and checks its ABI before it ever loads. Remove it any time with loadr plugin remove data-cleanup.