Your First Contract
Quick Start showed a passing write. This walks through making one fail — the moment that actually demonstrates what Invaract is for — using a contract already included in the repository, run directly against the real demo job.
-
Build the modules once
Section titled “Build the modules once”If you haven’t already:
Terminal window ./dev/build -
Look at the broken contract
Section titled “Look at the broken contract”demo/contracts/invaract_output_broken_example.yamlis identical to the working contract, except its output schema declares acustomer_namefield:outputs:- name: resultlocation: demo/output/result_broken_example.parquetformat: parquetschema:fields:- name: idtype: integer# ...- name: customer_nametype: stringrequired: truenullable: falseThe real demo transformation (
InvaractPlugin) never produces acustomer_namecolumn — so this contract can never be satisfied by the job as written. -
Run the job against it
Section titled “Run the job against it”Invoke the same job the quick start used, passing the broken contract as the fourth argument:
Terminal window spark-submit \--class com.invaract.runner.DemoJobHarness \--master local[*] \--jars plugin/target/scala-2.12/invaract-spark-plugin-0.2.0.jar \runner/target/scala-2.12/invaract-spark-runner.jar \demo/input/sample.csv \demo/output/result_broken_example.parquet \demo/output/report_broken_example.json \demo/contracts/invaract_output_broken_example.yaml -
Read the rejection
Section titled “Read the rejection”The job exits non-zero, and prints exactly what was wrong:
Contract violation: 'invaract_demo_output@1.0.0' rejected this transformation. Write aborted.What the contract expects:input 'orders' at demo/input/sample.csv: id: integer, value: integeroutput 'result' at demo/output/result_broken_example.parquet: id: integer, value: integer, value_squared: integer, value_tier: string, customer_name: stringWhat the plan contains:Write(file:/.../demo/output/result_broken_example.parquet, format=parquet, saveMode=overwrite)└─ Project├─ Project│ ├─ Read(file:/.../demo/input/sample.csv)│ ├─ id = id│ ├─ value = value│ └─ value_squared = (value * value)├─ id = id├─ value = value├─ value_squared = value_squared└─ value_tier = CASE WHEN value > 50 THEN high ELSE low ENDWhy it violates the contract (1 violation):1. [MISSING_OUTPUT_FIELD] required field 'customer_name' is absent from the actual OUTPUT schemaHow to correct it:1. Add a 'customer_name' column (type 'string') to the output, or mark it optional in the contract if it isn't always produced. -
Confirm nothing was written
Section titled “Confirm nothing was written”Terminal window ls demo/output/result_broken_example.parquetThe file does not exist. Spark never got to execute the write — Invaract rejected the plan during analysis, before any output was produced.
What’s next
Section titled “What’s next”Now that you’ve seen a contract reject a real write, learn the full format so you can write your own: Write a Contract.