Skip to content

Dependencies

Control the order of guarantee execution using requires, after, and before clauses.

Why Dependencies Matter

Sometimes guarantees must happen in a specific order:

ens
# Wrong - might try to encrypt before file exists!
ensure encrypted on file "secrets.db"
ensure exists on file "secrets.db"

EnsuraScript's implication system handles many dependencies automatically (encrypted implies exists), but sometimes you need explicit control.

Dependency Clauses

requires - Logical Prerequisite

ens
ensure <condition-A> requires <condition-B>

Condition A requires condition B to be satisfied first.

ens
ensure backed_up requires encrypted

Before backing up, ensure encryption is complete.

after - Temporal Ordering

ens
ensure <condition> after <resource>

This guarantee runs after all guarantees on the specified resource.

ens
ensure startup on service "app" after file "config.yaml" exists

Don't start the service until the config file is ready.

before - Reverse Temporal Ordering

ens
ensure <condition> before <resource>

This guarantee runs before all guarantees on the specified resource.

ens
ensure exists on file "config.yaml" before service "app" startup

Ensure config exists before the service starts.

Examples

Requires - Logical Dependencies

ens
on file "database.db" {
  ensure exists
  ensure encrypted with AES:256 key "env:DB_KEY"
  ensure backed_up requires encrypted
}

The backup won't start until encryption is verified.

After - Service Startup

ens
resource file "/etc/app/config.yaml" as config
resource service "myapp" as app

ensure exists on config
ensure readable on config

ensure running on app after config

(Note: service resource type is parsed but not yet implemented)

Before - Preparation Steps

ens
ensure exists on file "/var/log/app.log" before file "/usr/bin/app" startup

Create the log file before starting the application.

Combining Dependencies

You can use multiple dependency clauses:

ens
ensure backed_up requires encrypted after database "mydb" ready

This reads as: "Ensure backed_up, but only after:

  1. encrypted is satisfied (requires)
  2. All guarantees on database mydb are satisfied (after)

Implication vs. Explicit Dependencies

Automatic (Implication)

ens
ensure encrypted on file "secrets.db"
# Automatically ensures: exists, readable, writable FIRST

Explicit (Dependencies)

ens
ensure backed_up requires encrypted
# YOU specify that backed_up depends on encrypted

Use implication when possible (less code), use explicit dependencies for business logic ordering.

Dependency Graph

EnsuraScript builds a dependency graph from:

  1. Implication rules (automatic)
  2. requires clauses (explicit)
  3. after/before clauses (explicit)

Then it performs topological sorting to determine execution order.

View the execution order:

bash
ensura plan config.ens

View the dependency graph as DOT format:

bash
ensura compile config.ens --graph

Cycle Detection

If dependencies create a cycle, compilation fails:

ens
ensure A requires B
ensure B requires C
ensure C requires A  # CYCLE!

Error:

Compilation error: Dependency cycle detected: A → B → C → A

Next Steps

Continue to Collections & Invariants to learn how to enforce guarantees across multiple resources.

Released under the MIT License.