Übung 6 · Consumer-driven Contracts
Abhängigkeiten mit einem Consumer-driven Contract explizit machen.
Abhängigkeiten mit einem Consumer-driven Contract explizit machen.
Deine View aus der vorigen Übung liest direkt die Tabellen des Produzenten.
Sie hängt implizit vom gesamten orders_v2-Kontrakt ab, braucht aber nur fünf Felder.
Das Orders-Team kann nicht erkennen, ob eine Änderung dich bricht.
Mach die Abhängigkeit explizit: ein Consumer-driven Contract für genau die Felder, die du brauchst, und Views, die nur diese Felder bereitstellen.
Kopiere den orders_v2-Kontrakt und öffne die Kopie im Editor:
cp orders_v2.odcs.yaml orders_v2.consumer_sku_sales.odcs.yaml
datacontract edit orders_v2.consumer_sku_sales.odcs.yamlEditing: /Users/you/learn.datacontract.com/orders_v2.consumer_sku_sales.odcs.yaml
Data Contract Editor running at http://localhost:4243
Press Ctrl+C to stopSetze die ID auf orders_v2_consumer_sku_sales. Lass die Version bei 2.0.0, da der Kontrakt auf den v2-Daten basiert.
Entferne alle Properties, die deine View nicht nutzt, samt ihren Quality Checks. Behalte nur:
orders: order_id, order_timestampline_items: order_id, sku, quantityBehalte den Check quantity > 0. Dein Datenprodukt verlässt sich darauf: Sonst könnte total_quantity kleiner als order_count sein.
Die Kopie enthält auch context und synonyms des Produzenten (ODCS 3.2). Entferne den context auf Kontrakt-Ebene: Seine Verified Statements fragen order_total und die Tabellen des Produzenten ab, und sein Constraint betrifft ein Feld, das du entfernt hast. Kontext und Synonyme auf Schema-Ebene für behaltene Felder dürfen bleiben.
Das ist jetzt dein Kontrakt, nicht der des Orders-Teams:
team und support auf das Purchasing-Analytics-Team (wie in deinem sku_sales_per_year-Kontrakt),description.purpose neu, z. B. „The fields the SKU Sales data product actually needs from orders_v2“.Deine Zugriffs-Views liegen in einem neuen Schema sku_sales_input:
sku_sales_input,physicalType beider Schema-Objekte auf VIEW,quantity > 0 eine SQL-Query ist, ändere darin orders_v2. in sku_sales_input.. Sonst testet er weiter die alten Tabellen.datacontract test orders_v2.consumer_sku_sales.odcs.yamlTesting orders_v2.consumer_sku_sales.odcs.yaml
Server: postgres (type=postgres, host=localhost, port=5433, database=workshop,
schema=sku_sales_input)
╭────────┬───────────────────────────────┬────────────────────────┬────────────────────────────────╮
│ Result │ Check │ Field │ Details │
├────────┼───────────────────────────────┼────────────────────────┼────────────────────────────────┤
│ failed │ Check that field 'order_id' │ line_items.order_id │ Could not read model │
│ │ is present │ │ 'line_items': line_items │
…
🔴 data contract is invalid, found the following errors:
1) 7 checks on orders.order_id, orders.order_timestamp: Could not read model 'orders': orders
2) 9 checks on line_items.order_id, line_items.sku, line_items.quantity: Could not read model
'line_items': line_itemsSie schlagen fehl, weil es die Views noch nicht gibt. Contract-first, schon wieder.
Lege sql/sku_sales_input.sql mit Views an, die nur die vereinbarten Felder bereitstellen:
CREATE SCHEMA IF NOT EXISTS sku_sales_input;
CREATE OR REPLACE VIEW sku_sales_input.orders AS
SELECT order_id, order_timestamp FROM orders_v2.orders;
CREATE OR REPLACE VIEW sku_sales_input.line_items AS
SELECT order_id, sku, quantity FROM orders_v2.line_items;Wende sie an:
docker compose exec -T postgres psql -U workshop -d workshop < sql/sku_sales_input.sqlCREATE SCHEMA
CREATE VIEW
CREATE VIEWdatacontract test orders_v2.consumer_sku_sales.odcs.yamlTesting orders_v2.consumer_sku_sales.odcs.yaml
Server: postgres (type=postgres, host=localhost, port=5433, database=workshop,
schema=sku_sales_input)
╭────────┬──────────────────────────────────────────────────────┬────────────────────────┬─────────╮
│ Result │ Check │ Field │ Details │
├────────┼──────────────────────────────────────────────────────┼────────────────────────┼─────────┤
│ passed │ Check that field 'order_id' is present │ line_items.order_id │ │
│ passed │ Check that field order_id has physical type text │ line_items.order_id │ │
│ passed │ Check that field order_id has no missing values │ line_items.order_id │ │
│ passed │ Check that field 'quantity' is present │ line_items.quantity │ │
│ passed │ Check that field quantity has physical type bigint │ line_items.quantity │ │
│ passed │ Ensure quantity is positive │ line_items.quantity │ │
…
│ passed │ Check that field 'order_timestamp' is present │ orders.order_timestamp │ │
╰────────┴──────────────────────────────────────────────────────┴────────────────────────┴─────────╯
🟢 data contract is valid. Run 16 checks. Took 0.545395 seconds.Ändere sql/sku_sales_per_year.sql, sodass die View aus sku_sales_input.orders und sku_sales_input.line_items liest statt aus den orders_v2-Tabellen. Wende sie erneut an:
docker compose exec -T postgres psql -U workshop -d workshop < sql/sku_sales_per_year.sqlNOTICE: schema "analytics" already exists, skipping
CREATE SCHEMA
CREATE VIEWDie Ausgabe deines Datenprodukts darf sich nicht ändern. Dein eigener Kontrakt beweist es:
datacontract test sku_sales_per_year.odcs.yamlTesting sku_sales_per_year.odcs.yaml
…
│ passed │ Ensure year is plausible │ year │ │
╰────────┴──────────────────────────────────────────────────────────┴────────────────┴─────────╯
🟢 data contract is valid. Run 15 checks. Took 0.606872 seconds.Dein Datenprodukt berührt jetzt nur die Felder aus deinem Consumer-driven Contract.
Alles andere in orders_v2 darf sich ändern, ohne dich zu brechen.
Noch besser: Das Orders-Team kann deinen Kontrakt in seiner CI-Pipeline ausführen und einen Breaking Change abfangen, bevor er live geht. So eine Pipeline baust du in der nächsten Übung.
datacontract changelog orders_v2.odcs.yaml orders_v2.consumer_sku_sales.odcs.yamlsku_sales_per_year.odps.yaml auf orders_v2_consumer_sku_sales zeigen. Sollte der Input-Port auf den Kontrakt des Produzenten verweisen oder auf deinen? Für beides gibt es gute Argumente.