From 5e8191aa4eacfe824f89ced5443d26c01aabcece Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:27:26 +0200 Subject: [PATCH 01/14] docs(java): read a DataWrapper by iterator, and build a Timeseries with setters `DataWrapper.getItems()` returns `Collection`, which has no `get(int)`, so the 27 `.getItems().get(0)` reads never compiled; the site's existing idiom is `.getItems().iterator().next()`. `Timeseries` has no static `of(...)` factory, and `NodeModel`'s setters are Lombok-generated and return `void`, so neither the factory nor the fluent chain that followed it existed. Build the series with plain setter statements. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/asset-health-score.mdx | 2 +- docs/advanced/demand-forecasting.mdx | 2 +- docs/advanced/kmeans-clustering.mdx | 2 +- docs/advanced/lstm-anomaly-detection.mdx | 2 +- docs/advanced/lstm-forecasting.mdx | 2 +- docs/advanced/pca-process-monitoring.mdx | 2 +- docs/advanced/predictive-maintenance.mdx | 2 +- docs/advanced/random-forest-soft-sensor.mdx | 2 +- docs/advanced/sustained-alarm-window.mdx | 2 +- docs/advanced/xgboost-failure-prediction.mdx | 2 +- docs/guides/detect-events.mdx | 2 +- docs/guides/ingest-timeseries.mdx | 2 +- docs/guides/query-and-aggregate.mdx | 2 +- docs/guides/work-with-units.mdx | 4 +++- .../agriculture-food/precision-farming.mdx | 8 ++++++-- .../industries/agriculture-food/salmon-farming.mdx | 8 ++++++-- .../built-environment/smart-buildings.mdx | 2 +- docs/industries/energy-utilities/air-quality.mdx | 12 +++++++++--- docs/industries/energy-utilities/grid.mdx | 2 +- docs/industries/energy-utilities/waste.mdx | 2 +- docs/industries/energy-utilities/wind.mdx | 10 +++++++--- .../financial-services/portfolio-risk.mdx | 9 +++++---- docs/industries/healthcare/patient-flow.mdx | 2 +- docs/industries/manufacturing-process/discrete.mdx | 10 +++++++--- docs/industries/manufacturing-process/pharma.mdx | 7 ++++--- .../manufacturing-process/semiconductor.mdx | 7 ++++--- docs/industries/mining-metals/operations.mdx | 4 ++-- docs/industries/mining-metals/processing-plant.mdx | 2 +- docs/industries/oil-and-gas/emissions.mdx | 2 +- docs/industries/oil-and-gas/production.mdx | 2 +- docs/industries/oil-and-gas/refining.mdx | 2 +- docs/industries/technology-operations/network.mdx | 2 +- docs/industries/transport-logistics/ports.mdx | 2 +- docs/industries/transport-logistics/retail.mdx | 7 ++++--- docs/quickstart.mdx | 4 +++- docs/tutorial.mdx | 14 ++++++++------ 36 files changed, 91 insertions(+), 59 deletions(-) diff --git a/docs/advanced/asset-health-score.mdx b/docs/advanced/asset-health-score.mdx index bad073a..108f410 100644 --- a/docs/advanced/asset-health-score.mdx +++ b/docs/advanced/asset-health-score.mdx @@ -70,7 +70,7 @@ filter.setLimit(100); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); double bearingTemp = Double.parseDouble(pts.get(pts.size() - 1).getValue()); ``` diff --git a/docs/advanced/demand-forecasting.mdx b/docs/advanced/demand-forecasting.mdx index 3ff85c8..250bea7 100644 --- a/docs/advanced/demand-forecasting.mdx +++ b/docs/advanced/demand-forecasting.mdx @@ -68,7 +68,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var history = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var history = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/kmeans-clustering.mdx b/docs/advanced/kmeans-clustering.mdx index c86fdef..3fe3111 100644 --- a/docs/advanced/kmeans-clustering.mdx +++ b/docs/advanced/kmeans-clustering.mdx @@ -78,7 +78,7 @@ filter.setGranularity("30d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -var sig = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var sig = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/lstm-anomaly-detection.mdx b/docs/advanced/lstm-anomaly-detection.mdx index 6485ad4..0daa7cb 100644 --- a/docs/advanced/lstm-anomaly-detection.mdx +++ b/docs/advanced/lstm-anomaly-detection.mdx @@ -73,7 +73,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/lstm-forecasting.mdx b/docs/advanced/lstm-forecasting.mdx index 4cf5555..6c5ef90 100644 --- a/docs/advanced/lstm-forecasting.mdx +++ b/docs/advanced/lstm-forecasting.mdx @@ -74,7 +74,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/pca-process-monitoring.mdx b/docs/advanced/pca-process-monitoring.mdx index 067744c..0da9de7 100644 --- a/docs/advanced/pca-process-monitoring.mdx +++ b/docs/advanced/pca-process-monitoring.mdx @@ -80,7 +80,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/predictive-maintenance.mdx b/docs/advanced/predictive-maintenance.mdx index 288b594..1e0f5e9 100644 --- a/docs/advanced/predictive-maintenance.mdx +++ b/docs/advanced/predictive-maintenance.mdx @@ -73,7 +73,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/random-forest-soft-sensor.mdx b/docs/advanced/random-forest-soft-sensor.mdx index 4a8cb9c..77a596f 100644 --- a/docs/advanced/random-forest-soft-sensor.mdx +++ b/docs/advanced/random-forest-soft-sensor.mdx @@ -74,7 +74,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index dc8f3dc..76de57f 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -257,7 +257,7 @@ filter.setLimit(10000); DataRetriever request = new DataRetriever<>(); request.setItems(List.of(filter)); var points = client.timeseries().retrieve(request) - .getItems().get(0).getDatapoints(); + .getItems().iterator().next().getDatapoints(); SustainedHigh detector = new SustainedHigh(SERIES); final double LIMIT = SustainedHigh.LIMIT; diff --git a/docs/advanced/xgboost-failure-prediction.mdx b/docs/advanced/xgboost-failure-prediction.mdx index 109e98a..dc7d97b 100644 --- a/docs/advanced/xgboost-failure-prediction.mdx +++ b/docs/advanced/xgboost-failure-prediction.mdx @@ -76,7 +76,7 @@ filter.setGranularity("7d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -var agg = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); +var agg = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); ``` diff --git a/docs/guides/detect-events.mdx b/docs/guides/detect-events.mdx index e9d4986..d13e1e0 100644 --- a/docs/guides/detect-events.mdx +++ b/docs/guides/detect-events.mdx @@ -36,7 +36,7 @@ filter.setEnd(ZonedDateTime.now()); var request = new DataRetriever(); request.setItems(List.of(filter)); -var series = client.timeseries().retrieve(request).getItems().get(0); +var series = client.timeseries().retrieve(request).getItems().iterator().next(); boolean tooHot = series.getDatapoints().stream() .anyMatch(p -> Double.parseDouble(p.getValue()) > 110.0); diff --git a/docs/guides/ingest-timeseries.mdx b/docs/guides/ingest-timeseries.mdx index cc7801c..0ff95d9 100644 --- a/docs/guides/ingest-timeseries.mdx +++ b/docs/guides/ingest-timeseries.mdx @@ -210,7 +210,7 @@ firstHour.setLimit(10_000); DataRetriever request = new DataRetriever<>(); request.setItems(List.of(firstHour)); -int n = client.timeseries().retrieve(request).getItems().get(0).getDatapoints().size(); +int n = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints().size(); System.out.printf("%d readings in the first hour%n", n); if (n < 3600) throw new IllegalStateException("expected 3600 readings, got " + n); ``` diff --git a/docs/guides/query-and-aggregate.mdx b/docs/guides/query-and-aggregate.mdx index a757061..9efdab8 100644 --- a/docs/guides/query-and-aggregate.mdx +++ b/docs/guides/query-and-aggregate.mdx @@ -181,7 +181,7 @@ do { var request = new DataRetriever(); request.setItems(List.of(filter)); - var page = client.timeseries().retrieve(request).getItems().get(0); + var page = client.timeseries().retrieve(request).getItems().iterator().next(); page.getDatapoints().forEach(p -> handle(p)); cursor = page.getNextCursor(); } while (cursor != null); diff --git a/docs/guides/work-with-units.mdx b/docs/guides/work-with-units.mdx index efe48d1..b2b079c 100644 --- a/docs/guides/work-with-units.mdx +++ b/docs/guides/work-with-units.mdx @@ -54,7 +54,9 @@ and Rust examples set `float`); it describes what the numbers mean. ```java -var series = Timeseries.of("wellhead_pressure_bar").name("Wellhead pressure"); +var series = new Timeseries(); +series.setExternalId("wellhead_pressure_bar"); +series.setName("Wellhead pressure"); series.setUnit("bar"); series.setUnitExternalId("pressure_bar"); client.timeseries().create(series); diff --git a/docs/industries/agriculture-food/precision-farming.mdx b/docs/industries/agriculture-food/precision-farming.mdx index f887911..5bc0aa7 100644 --- a/docs/industries/agriculture-food/precision-farming.mdx +++ b/docs/industries/agriculture-food/precision-farming.mdx @@ -42,9 +42,13 @@ A farm *contains* fields; each field's sensors are series. ```java -var moisture = Timeseries.of("field_north_40_soil_moisture").name("North 40 soil moisture"); +var moisture = new Timeseries(); +moisture.setExternalId("field_north_40_soil_moisture"); +moisture.setName("North 40 soil moisture"); moisture.setUnit("pct"); -var soilTemp = Timeseries.of("field_north_40_soil_temp_c").name("North 40 soil temperature"); +var soilTemp = new Timeseries(); +soilTemp.setExternalId("field_north_40_soil_temp_c"); +soilTemp.setName("North 40 soil temperature"); soilTemp.setUnit("deg_c"); client.timeseries().create(moisture, soilTemp); diff --git a/docs/industries/agriculture-food/salmon-farming.mdx b/docs/industries/agriculture-food/salmon-farming.mdx index e27e997..11dc209 100644 --- a/docs/industries/agriculture-food/salmon-farming.mdx +++ b/docs/industries/agriculture-food/salmon-farming.mdx @@ -117,9 +117,13 @@ See [Query & aggregate](/guides/query-and-aggregate). ```java -var feed = Timeseries.of("pen_h_07_feed_kg").name("Pen H-07 feed"); +var feed = new Timeseries(); +feed.setExternalId("pen_h_07_feed_kg"); +feed.setName("Pen H-07 feed"); feed.setUnit("kg"); -var biomass = Timeseries.of("pen_h_07_biomass_kg").name("Pen H-07 biomass"); +var biomass = new Timeseries(); +biomass.setExternalId("pen_h_07_biomass_kg"); +biomass.setName("Pen H-07 biomass"); biomass.setUnit("kg"); client.timeseries().create(feed, biomass); diff --git a/docs/industries/built-environment/smart-buildings.mdx b/docs/industries/built-environment/smart-buildings.mdx index 73027d6..dbce800 100644 --- a/docs/industries/built-environment/smart-buildings.mdx +++ b/docs/industries/built-environment/smart-buildings.mdx @@ -127,7 +127,7 @@ filter.setGranularity("1d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> chartDailyKwh(p.getTimestamp(), p.getValue())); ``` diff --git a/docs/industries/energy-utilities/air-quality.mdx b/docs/industries/energy-utilities/air-quality.mdx index 43acd37..d5b1b39 100644 --- a/docs/industries/energy-utilities/air-quality.mdx +++ b/docs/industries/energy-utilities/air-quality.mdx @@ -80,11 +80,17 @@ every value is self-describing and a chart can label its axis correctly. ```java -var pm25 = Timeseries.of("station_kirkeveien_pm25").name("Kirkeveien PM2.5"); +var pm25 = new Timeseries(); +pm25.setExternalId("station_kirkeveien_pm25"); +pm25.setName("Kirkeveien PM2.5"); pm25.setUnit("ug_m3"); -var no2 = Timeseries.of("station_kirkeveien_no2").name("Kirkeveien NO2"); +var no2 = new Timeseries(); +no2.setExternalId("station_kirkeveien_no2"); +no2.setName("Kirkeveien NO2"); no2.setUnit("ppb"); -var co = Timeseries.of("station_kirkeveien_co").name("Kirkeveien CO"); +var co = new Timeseries(); +co.setExternalId("station_kirkeveien_co"); +co.setName("Kirkeveien CO"); co.setUnit("ppm"); client.timeseries().create(pm25, no2, co); ``` diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index 3bddbf9..f9486c0 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -122,7 +122,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> chart(p.getTimestamp(), p.getValue())); // hourly load ``` diff --git a/docs/industries/energy-utilities/waste.mdx b/docs/industries/energy-utilities/waste.mdx index 336f4d6..9527ed5 100644 --- a/docs/industries/energy-utilities/waste.mdx +++ b/docs/industries/energy-utilities/waste.mdx @@ -41,7 +41,7 @@ Each bin reports its fill level. When a bin crosses its collection threshold, ra ```java var series = client.timeseries().retrieve(lastReadingOf("bin_grunerlokka_114_fill_pct")) - .getItems().get(0); + .getItems().iterator().next(); double fill = Double.parseDouble(series.getDatapoints().get(0).getValue()); if (fill >= 80.0) { diff --git a/docs/industries/energy-utilities/wind.mdx b/docs/industries/energy-utilities/wind.mdx index 80f6350..c8c337d 100644 --- a/docs/industries/energy-utilities/wind.mdx +++ b/docs/industries/energy-utilities/wind.mdx @@ -43,9 +43,13 @@ Each turbine reports power and wind speed continuously. Hand the readings off in ```java -var power = Timeseries.of("turbine_t14_power_kw").name("Turbine T14 power"); +var power = new Timeseries(); +power.setExternalId("turbine_t14_power_kw"); +power.setName("Turbine T14 power"); power.setUnit("kw"); -var wind = Timeseries.of("turbine_t14_wind_ms").name("Turbine T14 wind speed"); +var wind = new Timeseries(); +wind.setExternalId("turbine_t14_wind_ms"); +wind.setName("Turbine T14 wind speed"); wind.setUnit("m_s"); client.timeseries().create(power, wind); @@ -124,7 +128,7 @@ var request = new DataRetriever(); request.setItems(List.of(filter)); double rated = 3500.0; // kW -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> recordCapacityFactor( p.getTimestamp(), Double.parseDouble(p.getValue()) / rated)); ``` diff --git a/docs/industries/financial-services/portfolio-risk.mdx b/docs/industries/financial-services/portfolio-risk.mdx index 7a25d20..a83f130 100644 --- a/docs/industries/financial-services/portfolio-risk.mdx +++ b/docs/industries/financial-services/portfolio-risk.mdx @@ -85,10 +85,11 @@ so currency amounts store faithfully. ```java -var mtm = Timeseries.of("portfolio_growth_mtm_usd") - .name("Growth portfolio — mark-to-market (USD)") - .setValueType("numeric") - .setDataSetId(deskId); +var mtm = new Timeseries(); +mtm.setExternalId("portfolio_growth_mtm_usd"); +mtm.setName("Growth portfolio — mark-to-market (USD)"); +mtm.setValueType("numeric"); +mtm.setDataSetId(deskId); mtm.setUnit("usd"); client.timeseries().create(mtm); diff --git a/docs/industries/healthcare/patient-flow.mdx b/docs/industries/healthcare/patient-flow.mdx index 83e1351..8af8926 100644 --- a/docs/industries/healthcare/patient-flow.mdx +++ b/docs/industries/healthcare/patient-flow.mdx @@ -52,7 +52,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> trackStage("time_to_bed", p.getTimestamp(), p.getValue())); ``` diff --git a/docs/industries/manufacturing-process/discrete.mdx b/docs/industries/manufacturing-process/discrete.mdx index e924eea..17fc295 100644 --- a/docs/industries/manufacturing-process/discrete.mdx +++ b/docs/industries/manufacturing-process/discrete.mdx @@ -42,9 +42,13 @@ series: `station_07_cycle_time_s`, `station_07_units`, `station_07_scrap`. ```java -var cycleTime = Timeseries.of("station_07_cycle_time_s").name("Station 07 cycle time"); +var cycleTime = new Timeseries(); +cycleTime.setExternalId("station_07_cycle_time_s"); +cycleTime.setName("Station 07 cycle time"); cycleTime.setUnit("s"); -var scrap = Timeseries.of("station_07_scrap").name("Station 07 scrap count"); +var scrap = new Timeseries(); +scrap.setExternalId("station_07_scrap"); +scrap.setName("Station 07 scrap count"); scrap.setUnit("count"); client.timeseries().create(cycleTime, scrap); @@ -113,7 +117,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> recordHourlyPerformance(p.getTimestamp(), p.getValue())); ``` diff --git a/docs/industries/manufacturing-process/pharma.mdx b/docs/industries/manufacturing-process/pharma.mdx index 253f984..c68f246 100644 --- a/docs/industries/manufacturing-process/pharma.mdx +++ b/docs/industries/manufacturing-process/pharma.mdx @@ -46,9 +46,10 @@ A bioreactor's pH, temperature and dissolved oxygen are the batch record. Use th ```java -var ph = Timeseries.of("batch_22f_ph") - .name("Batch 22F — pH") - .setValueType("numeric"); +var ph = new Timeseries(); +ph.setExternalId("batch_22f_ph"); +ph.setName("Batch 22F — pH"); +ph.setValueType("numeric"); ph.setUnit("ph"); client.timeseries().create(ph); diff --git a/docs/industries/manufacturing-process/semiconductor.mdx b/docs/industries/manufacturing-process/semiconductor.mdx index efc3f92..26ae2b7 100644 --- a/docs/industries/manufacturing-process/semiconductor.mdx +++ b/docs/industries/manufacturing-process/semiconductor.mdx @@ -47,9 +47,10 @@ exact — use the `NUMERIC` value type so values store without floating-point dr ```java -var pressure = Timeseries.of("tool_etch_07_chamber_pressure_mtorr") - .name("Etch-07 chamber pressure") - .setValueType("numeric"); +var pressure = new Timeseries(); +pressure.setExternalId("tool_etch_07_chamber_pressure_mtorr"); +pressure.setName("Etch-07 chamber pressure"); +pressure.setValueType("numeric"); pressure.setUnit("mtorr"); client.timeseries().create(pressure); diff --git a/docs/industries/mining-metals/operations.mdx b/docs/industries/mining-metals/operations.mdx index 5e6e02d..31f9230 100644 --- a/docs/industries/mining-metals/operations.mdx +++ b/docs/industries/mining-metals/operations.mdx @@ -47,7 +47,7 @@ scrambled. See [Turn readings into events](/guides/detect-events). ```java var series = client.timeseries().retrieve(lastHourOf("truck_785_oil_pressure_kpa")) - .getItems().get(0); + .getItems().iterator().next(); if (series.getDatapoints().stream().anyMatch(p -> Double.parseDouble(p.getValue()) < 250.0)) { EventModel warning = new EventModel(); @@ -118,7 +118,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> compareToPlan(p.getTimestamp(), p.getValue())); ``` diff --git a/docs/industries/mining-metals/processing-plant.mdx b/docs/industries/mining-metals/processing-plant.mdx index 175c5e0..f2c6264 100644 --- a/docs/industries/mining-metals/processing-plant.mdx +++ b/docs/industries/mining-metals/processing-plant.mdx @@ -53,7 +53,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> compareToTarget(p.getTimestamp(), p.getValue())); // % recovery ``` diff --git a/docs/industries/oil-and-gas/emissions.mdx b/docs/industries/oil-and-gas/emissions.mdx index f0ae01e..8177c85 100644 --- a/docs/industries/oil-and-gas/emissions.mdx +++ b/docs/industries/oil-and-gas/emissions.mdx @@ -54,7 +54,7 @@ filter.setGranularity("1d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -double monthly = client.timeseries().retrieve(request).getItems().get(0) +double monthly = client.timeseries().retrieve(request).getItems().iterator().next() .getDatapoints().stream().mapToDouble(p -> Double.parseDouble(p.getValue())).sum(); ``` diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 503a91d..4d8b535 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -199,7 +199,7 @@ queries open events for the field, and the event references the well it concerns ```java var series = client.timeseries().retrieve(lastHourOf("pump_intake_pressure_bar")) - .getItems().get(0); + .getItems().iterator().next(); if (series.getDatapoints().stream().anyMatch(p -> Double.parseDouble(p.getValue()) < 80.0)) { EventModel event = new EventModel(); diff --git a/docs/industries/oil-and-gas/refining.mdx b/docs/industries/oil-and-gas/refining.mdx index 01065a4..5149a42 100644 --- a/docs/industries/oil-and-gas/refining.mdx +++ b/docs/industries/oil-and-gas/refining.mdx @@ -53,7 +53,7 @@ var request = new DataRetriever(); request.setItems(List.of(filter)); // divide hourly energy by hourly throughput for energy-per-barrel -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> recordEnergyIntensity(p.getTimestamp(), p.getValue())); ``` diff --git a/docs/industries/technology-operations/network.mdx b/docs/industries/technology-operations/network.mdx index 3c1fe0a..4880d67 100644 --- a/docs/industries/technology-operations/network.mdx +++ b/docs/industries/technology-operations/network.mdx @@ -63,7 +63,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> flagIfSaturated(p.getTimestamp(), p.getValue())); // PRB utilisation % ``` diff --git a/docs/industries/transport-logistics/ports.mdx b/docs/industries/transport-logistics/ports.mdx index 9c01bfd..01a03ae 100644 --- a/docs/industries/transport-logistics/ports.mdx +++ b/docs/industries/transport-logistics/ports.mdx @@ -52,7 +52,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().get(0).getDatapoints() +client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() .forEach(p -> compareToTarget(p.getTimestamp(), p.getValue())); // moves/hour ``` diff --git a/docs/industries/transport-logistics/retail.mdx b/docs/industries/transport-logistics/retail.mdx index dbde095..863a5b8 100644 --- a/docs/industries/transport-logistics/retail.mdx +++ b/docs/industries/transport-logistics/retail.mdx @@ -48,9 +48,10 @@ region.setName("Nordics region"); long regionId = client.datasets().create(List.of(region)) .getItems().iterator().next().getId(); -var salesSeries = Timeseries.of("store_oslo_01_sku_4471_sales") - .name("Oslo 01 — SKU 4471 units sold") - .setDataSetId(regionId); +var salesSeries = new Timeseries(); +salesSeries.setExternalId("store_oslo_01_sku_4471_sales"); +salesSeries.setName("Oslo 01 — SKU 4471 units sold"); +salesSeries.setDataSetId(regionId); salesSeries.setUnit("units"); client.timeseries().create(salesSeries); ``` diff --git a/docs/quickstart.mdx b/docs/quickstart.mdx index a8918f0..015d500 100644 --- a/docs/quickstart.mdx +++ b/docs/quickstart.mdx @@ -102,7 +102,9 @@ TOKEN=eyJhbGciOi... # or CLIENT_ID / CLIENT_SECRET / TOKEN_URI ```java var client = DatahubClient.fromEnv(); -var series = Timeseries.of("engine_temperature").name("Engine temperature"); +var series = new Timeseries(); +series.setExternalId("engine_temperature"); +series.setName("Engine temperature"); series.setUnit("celsius"); series.setValueType("float"); client.timeseries().create(series); diff --git a/docs/tutorial.mdx b/docs/tutorial.mdx index 948e5ad..24de745 100644 --- a/docs/tutorial.mdx +++ b/docs/tutorial.mdx @@ -262,9 +262,10 @@ Set existing = client.timeseries().byIds(lookups).getItems().stream() List missing = METRICS.stream() .filter(m -> !existing.contains(m.baseId() + "_" + host)) .map(m -> { - Timeseries ts = Timeseries.of(m.baseId() + "_" + host) - .name(m.name() + " (" + host + ")") - .setValueType("BIGINT"); + Timeseries ts = new Timeseries(); + ts.setExternalId(m.baseId() + "_" + host); + ts.setName(m.name() + " (" + host + ")"); + ts.setValueType("BIGINT"); ts.setUnit("bytes"); return ts; }) @@ -742,9 +743,10 @@ public final class MemoryIngestTutorial { List missing = METRICS.stream() .filter(m -> !existing.contains(m.baseId() + "_" + host)) .map(m -> { - Timeseries ts = Timeseries.of(m.baseId() + "_" + host) - .name(m.name() + " (" + host + ")") - .setValueType("BIGINT"); + Timeseries ts = new Timeseries(); + ts.setExternalId(m.baseId() + "_" + host); + ts.setName(m.name() + " (" + host + ")"); + ts.setValueType("BIGINT"); ts.setUnit("bytes"); return ts; }) From fc865177bbb213fdf35fa08a496046b71982b36e Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:41:58 +0200 Subject: [PATCH 02/14] docs(java): the classes and signatures the SDK actually has MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `ResourceForm` never existed — resources are created from `Resource` (a `NodeModel`), which is what `resources().create` takes. `ResourceSearch` was replaced by `SearchBody`; its own javadoc names it as one of the four classes it folded together. `resources().create` answers with `GraphDataWrapper`. `ResourceNetwork.nodes()` is a `Set`, so the 16 traversals that mapped `Resource::getExternalId` over it named a receiver the stream never holds. `timeseries().list(int, long)` takes the data set's numeric id; there is no overload for an external id. `DataSetFilter` has no `externalIdPrefix`, so the retail page now looks its data set up with `datasets().byIds`, which is what its Python and Rust tabs beside it already did. The tutorial's step path used a `Metric` record that only appeared in the complete program at the end of the page, so a reader following the steps could not compile step 2. It is introduced where the steps first need it. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/guides/correlate-alarms.mdx | 4 ++-- docs/guides/model-assets-graph.mdx | 12 ++++++------ docs/industries/built-environment/construction.mdx | 4 ++-- docs/industries/energy-utilities/grid.mdx | 4 ++-- docs/industries/energy-utilities/water.mdx | 4 ++-- docs/industries/financial-services/aml.mdx | 2 +- .../financial-services/insurance-fraud.mdx | 2 +- docs/industries/healthcare/hospital-operations.mdx | 4 ++-- docs/industries/healthcare/medical-devices.mdx | 2 +- .../manufacturing-process/semiconductor.mdx | 4 ++-- docs/industries/oil-and-gas/production.mdx | 10 +++++----- .../technology-operations/data-centers.mdx | 4 ++-- docs/industries/technology-operations/network.mdx | 4 ++-- .../technology-operations/observability.mdx | 8 ++++---- docs/industries/transport-logistics/aerospace.mdx | 4 ++-- docs/industries/transport-logistics/retail.mdx | 8 +++++--- docs/reference/resources.md | 8 ++++---- docs/reference/timeseries.md | 14 +++++++------- docs/tutorial.mdx | 7 +++++++ 19 files changed, 59 insertions(+), 50 deletions(-) diff --git a/docs/guides/correlate-alarms.mdx b/docs/guides/correlate-alarms.mdx index 8aeec73..99f9b00 100644 --- a/docs/guides/correlate-alarms.mdx +++ b/docs/guides/correlate-alarms.mdx @@ -96,10 +96,10 @@ subsystem both alarms belong to, the likely common cause. ```java Set aNodes = na.nodes().stream() - .map(Resource::getExternalId).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).collect(Collectors.toSet()); Set shared = nb.nodes().stream() - .map(Resource::getExternalId) + .map(NodeModel::getExternalId) .filter(aNodes::contains) .collect(Collectors.toSet()); shared.remove("sensor_a"); diff --git a/docs/guides/model-assets-graph.mdx b/docs/guides/model-assets-graph.mdx index b40c695..f0e2f49 100644 --- a/docs/guides/model-assets-graph.mdx +++ b/docs/guides/model-assets-graph.mdx @@ -26,17 +26,17 @@ well in code, not because the server requires it. ```java -ResourceForm plant = new ResourceForm(); +Resource plant = new Resource(); plant.setExternalId("plant_oslo"); plant.setName("Oslo Plant"); plant.setLabels(List.of("Plant")); // at least one label is required -ResourceForm line = new ResourceForm(); +Resource line = new Resource(); line.setExternalId("line_a"); line.setName("Assembly line A"); line.setLabels(List.of("Line")); -ResourceForm press = new ResourceForm(); +Resource press = new Resource(); press.setExternalId("press_07"); press.setName("Hydraulic press 07"); press.setLabels(List.of("Machine")); @@ -126,9 +126,9 @@ it with a relationship (`press_07` → `PRODUCES` → `press_07_oil_temp`), then ```java -Timeseries oilTemp = new Timeseries() - .setExternalId("press_07_oil_temp") - .setName("Press 07 oil temperature"); +Timeseries oilTemp = new Timeseries(); +oilTemp.setExternalId("press_07_oil_temp"); +oilTemp.setName("Press 07 oil temperature"); oilTemp.setUnit("celsius"); oilTemp.setUnitExternalId("temperature_deg_c"); client.timeseries().create(List.of(oilTemp)); diff --git a/docs/industries/built-environment/construction.mdx b/docs/industries/built-environment/construction.mdx index 3b0a18b..d054972 100644 --- a/docs/industries/built-environment/construction.mdx +++ b/docs/industries/built-environment/construction.mdx @@ -45,12 +45,12 @@ a crew can find the current revision instantly. See [Attach files](/guides/attac ```java -ResourceForm site = new ResourceForm(); +Resource site = new Resource(); site.setExternalId("site_harbour_tower"); site.setName("Harbour Tower"); site.setLabels(List.of("Site")); -ResourceForm zone = new ResourceForm(); +Resource zone = new Resource(); zone.setExternalId("zone_level_12"); zone.setName("Level 12"); zone.setLabels(List.of("Zone")); diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index f9486c0..642ae32 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -43,12 +43,12 @@ A region *contains* substations, a substation *contains* transformers, a transfo ```java -ResourceForm region = new ResourceForm(); +Resource region = new Resource(); region.setExternalId("grid_region_east"); region.setName("Eastern region"); region.setLabels(List.of("Region")); -ResourceForm substation = new ResourceForm(); +Resource substation = new Resource(); substation.setExternalId("substation_oslo_1"); substation.setName("Oslo substation 1"); substation.setLabels(List.of("Substation")); diff --git a/docs/industries/energy-utilities/water.mdx b/docs/industries/energy-utilities/water.mdx index e434f1d..1597bc9 100644 --- a/docs/industries/energy-utilities/water.mdx +++ b/docs/industries/energy-utilities/water.mdx @@ -101,9 +101,9 @@ ResourceNetwork west = client.resources().fetchRelated("zone_west_12", 20); ResourceNetwork east = client.resources().fetchRelated("zone_east_07", 20); Set westUpstream = west.nodes().stream() - .map(Resource::getExternalId).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).collect(Collectors.toSet()); Set common = east.nodes().stream() - .map(Resource::getExternalId).filter(westUpstream::contains).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).filter(westUpstream::contains).collect(Collectors.toSet()); // common holds main_trunk_north (and source_lake_a) → isolate there ``` diff --git a/docs/industries/financial-services/aml.mdx b/docs/industries/financial-services/aml.mdx index ea4f92a..2936ad7 100644 --- a/docs/industries/financial-services/aml.mdx +++ b/docs/industries/financial-services/aml.mdx @@ -97,7 +97,7 @@ through. Other flagged accounts in the same cluster are the ring. ResourceNetwork ring = client.resources().fetchRelated("account_77310", 5); ring.nodes().stream() - .map(Resource::getExternalId) + .map(NodeModel::getExternalId) .filter(id -> id.startsWith("account_")) .forEach(a -> System.out.println("linked account: " + a)); ``` diff --git a/docs/industries/financial-services/insurance-fraud.mdx b/docs/industries/financial-services/insurance-fraud.mdx index 1f4b4ce..5f35510 100644 --- a/docs/industries/financial-services/insurance-fraud.mdx +++ b/docs/industries/financial-services/insurance-fraud.mdx @@ -103,7 +103,7 @@ ResourceNetwork ring = client.resources().fetchRelated("claim_88421", 4); // other claims reachable through shared parties/phones/shops ring.nodes().stream() - .map(Resource::getExternalId) + .map(NodeModel::getExternalId) .filter(id -> id.startsWith("claim_") && !id.equals("claim_88421")) .forEach(c -> System.out.println("linked claim: " + c)); ``` diff --git a/docs/industries/healthcare/hospital-operations.mdx b/docs/industries/healthcare/hospital-operations.mdx index af7071a..c6b6992 100644 --- a/docs/industries/healthcare/hospital-operations.mdx +++ b/docs/industries/healthcare/hospital-operations.mdx @@ -45,12 +45,12 @@ for any physical estate, which lets a ward-level alert roll up to the whole site ```java -ResourceForm hospital = new ResourceForm(); +Resource hospital = new Resource(); hospital.setExternalId("hospital_central"); hospital.setName("Central Hospital"); hospital.setLabels(List.of("Hospital")); -ResourceForm ward = new ResourceForm(); +Resource ward = new Resource(); ward.setExternalId("ward_icu"); ward.setName("Intensive care"); ward.setLabels(List.of("Ward")); diff --git a/docs/industries/healthcare/medical-devices.mdx b/docs/industries/healthcare/medical-devices.mdx index 306d0dc..181f5a1 100644 --- a/docs/industries/healthcare/medical-devices.mdx +++ b/docs/industries/healthcare/medical-devices.mdx @@ -45,7 +45,7 @@ event for biomedical engineering. ```java -ResourceForm pump = new ResourceForm(); +Resource pump = new Resource(); pump.setExternalId("pump_icu_3391"); pump.setName("Infusion pump 3391"); pump.setLabels(List.of("Pump")); diff --git a/docs/industries/manufacturing-process/semiconductor.mdx b/docs/industries/manufacturing-process/semiconductor.mdx index 26ae2b7..b1577af 100644 --- a/docs/industries/manufacturing-process/semiconductor.mdx +++ b/docs/industries/manufacturing-process/semiconductor.mdx @@ -108,9 +108,9 @@ ResourceNetwork lotA = client.resources().fetchRelated("lot_22841", 6); ResourceNetwork lotB = client.resources().fetchRelated("lot_22863", 6); Set toolsA = lotA.nodes().stream() - .map(Resource::getExternalId).filter(id -> id.startsWith("tool_")).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).filter(id -> id.startsWith("tool_")).collect(Collectors.toSet()); Set suspect = lotB.nodes().stream() - .map(Resource::getExternalId).filter(toolsA::contains).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).filter(toolsA::contains).collect(Collectors.toSet()); // suspect contains "tool_etch_07" → the chamber to pull and check ``` diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 4d8b535..1f94d9b 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -58,17 +58,17 @@ Modeling it as a graph lets you walk from a field down to any individual sensor. ```java -ResourceForm field = new ResourceForm(); +Resource field = new Resource(); field.setExternalId("field_north_sea"); field.setName("North Sea field"); field.setLabels(List.of("Field")); -ResourceForm well = new ResourceForm(); +Resource well = new Resource(); well.setExternalId("well_a12"); well.setName("Well A-12"); well.setLabels(List.of("Well")); -ResourceForm pump = new ResourceForm(); +Resource pump = new Resource(); pump.setExternalId("pump_esp_a12"); pump.setName("ESP — Well A-12"); pump.setLabels(List.of("Pump")); @@ -265,9 +265,9 @@ ResourceNetwork na = client.resources().fetchRelated("wellhead_temp_a12", 5); ResourceNetwork nb = client.resources().fetchRelated("pump_temp_a12", 5); Set aNodes = na.nodes().stream() - .map(Resource::getExternalId).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).collect(Collectors.toSet()); Set shared = nb.nodes().stream() - .map(Resource::getExternalId).filter(aNodes::contains).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).filter(aNodes::contains).collect(Collectors.toSet()); // shared contains "cooling_system" → one root cause, not two ``` diff --git a/docs/industries/technology-operations/data-centers.mdx b/docs/industries/technology-operations/data-centers.mdx index 25a2b69..ab9f332 100644 --- a/docs/industries/technology-operations/data-centers.mdx +++ b/docs/industries/technology-operations/data-centers.mdx @@ -129,8 +129,8 @@ rack to the unit they share — the exact ResourceNetwork a = client.resources().fetchRelated("rack_r14", 3); ResourceNetwork b = client.resources().fetchRelated("rack_r15", 3); -Set aNodes = a.nodes().stream().map(Resource::getExternalId).collect(Collectors.toSet()); -Set shared = b.nodes().stream().map(Resource::getExternalId) +Set aNodes = a.nodes().stream().map(NodeModel::getExternalId).collect(Collectors.toSet()); +Set shared = b.nodes().stream().map(NodeModel::getExternalId) .filter(aNodes::contains).collect(Collectors.toSet()); // shared contains "crac_unit_2" → one failing unit, not two hot racks ``` diff --git a/docs/industries/technology-operations/network.mdx b/docs/industries/technology-operations/network.mdx index 4880d67..0838e6c 100644 --- a/docs/industries/technology-operations/network.mdx +++ b/docs/industries/technology-operations/network.mdx @@ -122,8 +122,8 @@ field team at the one link to fix instead of a dozen cells to chase. ResourceNetwork c1 = client.resources().fetchRelated("cell_oslo_4412", 4); ResourceNetwork c2 = client.resources().fetchRelated("cell_oslo_4418", 4); -Set n1 = c1.nodes().stream().map(Resource::getExternalId).collect(Collectors.toSet()); -Set shared = c2.nodes().stream().map(Resource::getExternalId) +Set n1 = c1.nodes().stream().map(NodeModel::getExternalId).collect(Collectors.toSet()); +Set shared = c2.nodes().stream().map(NodeModel::getExternalId) .filter(n1::contains).collect(Collectors.toSet()); // shared contains "backhaul_link_88" → fix the link, not the cells ``` diff --git a/docs/industries/technology-operations/observability.mdx b/docs/industries/technology-operations/observability.mdx index 43b2552..b72ecd2 100644 --- a/docs/industries/technology-operations/observability.mdx +++ b/docs/industries/technology-operations/observability.mdx @@ -51,12 +51,12 @@ on a host fan out to the services it affects. ```java -ResourceForm service = new ResourceForm(); +Resource service = new Resource(); service.setExternalId("service_checkout"); service.setName("Checkout service"); service.setLabels(List.of("Service")); -ResourceForm host = new ResourceForm(); +Resource host = new Resource(); host.setExternalId("host_web_01"); host.setName("web-01"); host.setLabels(List.of("Host")); @@ -235,9 +235,9 @@ ResourceNetwork checkout = client.resources().fetchRelated("service_checkout", 4 ResourceNetwork payments = client.resources().fetchRelated("service_payments", 4); Set checkoutDeps = checkout.nodes().stream() - .map(Resource::getExternalId).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).collect(Collectors.toSet()); Set shared = payments.nodes().stream() - .map(Resource::getExternalId).filter(checkoutDeps::contains).collect(Collectors.toSet()); + .map(NodeModel::getExternalId).filter(checkoutDeps::contains).collect(Collectors.toSet()); // shared contains "order_db" → one failing dependency, not two outages ``` diff --git a/docs/industries/transport-logistics/aerospace.mdx b/docs/industries/transport-logistics/aerospace.mdx index 9853d9f..53735a5 100644 --- a/docs/industries/transport-logistics/aerospace.mdx +++ b/docs/industries/transport-logistics/aerospace.mdx @@ -47,12 +47,12 @@ that shared node is what makes fleet-wide correlation possible. ```java -ResourceForm aircraft = new ResourceForm(); +Resource aircraft = new Resource(); aircraft.setExternalId("aircraft_ln_312"); aircraft.setName("Aircraft LN-312"); aircraft.setLabels(List.of("aircraft_ln_312")); -ResourceForm pump = new ResourceForm(); +Resource pump = new Resource(); pump.setExternalId("hyd_pump_ln_312_1"); pump.setName("Hydraulic pump #1"); pump.setLabels(List.of("hyd_pump_ln_312_1")); diff --git a/docs/industries/transport-logistics/retail.mdx b/docs/industries/transport-logistics/retail.mdx index 863a5b8..f7bac6b 100644 --- a/docs/industries/transport-logistics/retail.mdx +++ b/docs/industries/transport-logistics/retail.mdx @@ -102,9 +102,11 @@ replenishment. See [Datasets reference](/reference/datasets) and ```java -DataSetRetreiver retriever = new DataSetRetreiver(); -retriever.getFilter().setExternalIdPrefix("region_nordics"); // scope to the region's dataset -DataWrapper regional = client.datasets().filter(retriever); +import ai.intellistream.datahub.models.IdCollection; + +// scope to the region's dataset +DataWrapper regional = client.datasets().byIds( + List.of(IdCollection.createFromExternalId("region_nordics"))); ``` diff --git a/docs/reference/resources.md b/docs/reference/resources.md index 68546cd..f2c1b9a 100644 --- a/docs/reference/resources.md +++ b/docs/reference/resources.md @@ -266,12 +266,12 @@ retarget a relationship or change its type): ```java -ResourceForm plant = new ResourceForm(); +Resource plant = new Resource(); plant.setExternalId("plant_oslo"); plant.setName("Oslo Plant"); plant.setLabels(List.of("Plant")); -ResourceForm pump = new ResourceForm(); +Resource pump = new Resource(); pump.setExternalId("pump_1"); pump.setName("Pump 1"); pump.setLabels(List.of("Pump")); @@ -281,7 +281,7 @@ contains.setName("contains"); contains.setFromExternalId("plant_oslo"); contains.setToExternalId("pump_1"); -GraphDataWrapper created = client.resources() +GraphDataWrapper created = client.resources() .create(List.of(plant, pump), List.of(contains)); System.out.println(created.getNodes().size() + " resources, " @@ -518,7 +518,7 @@ search query itself, everything else is applied to the hits afterwards. ```java -ResourceSearch search = new ResourceSearch(); +SearchBody search = new SearchBody<>(); search.setLimit(10); search.getSearch().setQuery("pump"); DataWrapper matches = client.resources().search(search); diff --git a/docs/reference/timeseries.md b/docs/reference/timeseries.md index b916e86..798d82b 100644 --- a/docs/reference/timeseries.md +++ b/docs/reference/timeseries.md @@ -19,9 +19,9 @@ exactly as you send it. [External ids & naming →](./external-ids) ```java -Timeseries series = new Timeseries() - .setExternalId("engine_temperature") - .setName("Engine temperature"); +Timeseries series = new Timeseries(); +series.setExternalId("engine_temperature"); +series.setName("Engine temperature"); series.setUnit("celsius"); client.timeseries().create(List.of(series)); @@ -121,9 +121,9 @@ For a value that must reconcile exactly, use `numeric`: ```java -Timeseries price = new Timeseries() - .setExternalId("book_value_usd") - .setName("Book value (USD)"); +Timeseries price = new Timeseries(); +price.setExternalId("book_value_usd"); +price.setName("Book value (USD)"); price.setUnit("usd"); price.setValueType("numeric"); // exact decimals, no float rounding @@ -375,7 +375,7 @@ because the stored points would no longer parse; create a new series instead. import ai.intellistream.datahub.timeseries.UpdateTimeseries; DataWrapper newest = client.timeseries().list(100); -DataWrapper inSet = client.timeseries().list(100, "engine_data"); +DataWrapper inSet = client.timeseries().list(100, 43L); // Java takes the numeric dataSetId UpdateTimeseries change = new UpdateTimeseries().setExternalId("engine_temperature"); change.getUpdate().getDescription().set("Engine block temperature, port side"); diff --git a/docs/tutorial.mdx b/docs/tutorial.mdx index 24de745..7a99fa4 100644 --- a/docs/tutorial.mdx +++ b/docs/tutorial.mdx @@ -252,6 +252,13 @@ that's expected, not a bug. ```java +record Metric(String baseId, String name) {} + +List METRICS = List.of( + new Metric("system_memory_used", "System memory used"), + new Metric("system_memory_available", "System memory available"), + new Metric("system_swap_used", "System swap used")); + List lookups = METRICS.stream() .map(m -> IdCollection.createFromExternalId(m.baseId() + "_" + host)) .toList(); From 198514644b36806df585568a7d21d3643931b08c Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:41:58 +0200 Subject: [PATCH 03/14] test(compile): a reader's value cannot fail the call it is passed to MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit javac resolves neither an overload nor a target type through an argument it could not resolve, so an unresolved reader-supplied name is reported twice: once as the name, and again as a type error on the enclosing call — a different line, which is why the existing per-line suppression never caught it. Five pages were failing on calls that compile: `timeseries().ingest(Map.of(id, readings))` with `readings` left to the reader, and the tutorial's `host`. The stubbed pass already gives every such name a type, so it can now retract as well as add: a *typing* error that disappears once the reader's names are typed was theirs, not the page's. Lookups are untouched — a missing method or type still fails however the reader's values are typed — and `invalid method reference` stays hard, being a claim about the SDK's shape rather than about what flows into a call. The new `overload_with_reader_argument` control fails without this change. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- doctests/compile_check.py | 42 +++++++++++++++++++++++++++++++++++++-- doctests/test_compile.py | 6 ++++++ 2 files changed, 46 insertions(+), 2 deletions(-) diff --git a/doctests/compile_check.py b/doctests/compile_check.py index 67a3ff8..0eee703 100644 --- a/doctests/compile_check.py +++ b/doctests/compile_check.py @@ -555,12 +555,16 @@ def check_java(units: list[Unit], workdir: Path, classpath: str, timeout: int = u.segments = [replace(s, first_line=s.first_line + shift) for s in u.segments] out: dict[str, list[Diagnostic]] = {u.name: [] for u in units} + # line and "could a stub's type have caused this", so the second pass can retract it. + first: dict[str, list[tuple[int, Diagnostic, bool]]] = {u.name: [] for u in units} stubs: dict[str, dict[int, list[tuple[str, str]]]] = {} # unit -> line -> (kind, name) for e in _javac({f"{u.name}.java": u for u in units}, workdir, classpath, timeout): symbol, location = e.field("symbol"), e.field("location") text = e.message + (f": {symbol}" if symbol else "") + (f" (in {location})" if symbol and location else "") name = java_placeholder(e.message, symbol, location, e.unit.name) - out[e.unit.name].append(Diagnostic(e.unit.page, "java", e.unit.locate(e.line), text, name)) + diag = Diagnostic(e.unit.page, "java", e.unit.locate(e.line), text, name) + out[e.unit.name].append(diag) + first[e.unit.name].append((e.line, diag, name is None and _typing_failed(e))) if name and e.unit.program is None: kind = symbol.split()[0] stubs.setdefault(e.unit.name, {}).setdefault(e.line, []).append((kind, name)) @@ -590,7 +594,8 @@ def check_java(units: list[Unit], workdir: Path, classpath: str, timeout: int = if ln.startswith(f"public class {u.name} {{") else ln for ln in lines] stubbed[f"{u.name}.java"] = replace(u, source="\n".join(lines)) if stubbed: - for e in _javac(stubbed, workdir / "stubbed", classpath, timeout): + second = _javac(stubbed, workdir / "stubbed", classpath, timeout) + for e in second: if e.line not in stubs[e.unit.name] or not _lookup_failed(e): continue symbol, location = e.field("symbol"), e.field("location") @@ -599,6 +604,21 @@ def check_java(units: list[Unit], workdir: Path, classpath: str, timeout: int = diag = Diagnostic(e.unit.page, "java", e.unit.locate(e.line), text) if all((d.where, d.message) != (diag.where, diag.message) for d in out[e.unit.name]): out[e.unit.name].append(diag) + + # …and the same pass retracts, which the first one cannot do for itself. javac + # resolves neither an overload nor a target type through an argument it could not + # resolve, so an unresolved reader-supplied name shows up a second time as a type + # error — on the *enclosing call*, which is a different line from the name itself. + # Once every such name has a type, a type error that disappears was the name's and + # not the page's. Only typing errors are dropped this way; a missing method or type + # still fails however the reader's values are typed. + still: dict[str, set[int]] = {} + for e in second: + still.setdefault(e.unit.name, set()).add(e.line) + for unit_name in stubs: + resolved = [d for line, d, droppable in first[unit_name] + if droppable and line not in still.get(unit_name, set())] + out[unit_name] = [d for d in out[unit_name] if d not in resolved] return out @@ -621,6 +641,24 @@ def _lookup_failed(e: _JavacError) -> bool: return False +def _typing_failed(e: _JavacError) -> bool: + """An error about argument or target *types* — the kind an unresolved name also produces. + + The mirror of `_lookup_failed`, and used only to retract: a diagnostic of this kind that + the stubbed pass no longer reports came from a name the reader supplies, because javac + gives up on overload resolution and on inference as soon as one argument is erroneous. + + `invalid method reference` is deliberately not here. A method reference names its + receiver type outright, so it is a claim about the SDK's shape rather than about what + flows into a call, and it stays hard whatever the reader passes. + """ + if "invalid method reference" in e.message: + return False + return (e.message.startswith("incompatible types") + or e.message.startswith("no suitable method") + or "cannot be applied to given types" in e.message) + + def java_placeholder(msg: str, symbol: str | None, location: str | None, cls: str) -> str | None: """The name, when an error only says "this page never defines value/method X". diff --git a/doctests/test_compile.py b/doctests/test_compile.py index fa1ebf9..5bc5451 100644 --- a/doctests/test_compile.py +++ b/doctests/test_compile.py @@ -68,6 +68,12 @@ def page(self, lang: str) -> docblocks.Page: placeholders=frozenset({"readerValue", "recordReading"})), Control("missing_method_with_reader_argument", "client.timeseries().noSuchMethodForDoctest(readerValue);", hard_lines=(1,), placeholders=frozenset({"readerValue"})), + # `ingest` is overloaded (List and Map>), + # so javac reports the unresolved argument *and* an overload failure on the call. The + # call is the page's own and compiles once the reader's value has a type; only the + # argument is left to the reader. See `_typing_failed`. + Control("overload_with_reader_argument", 'client.timeseries().ingest(Map.of("x", readerReadings));', + placeholders=frozenset({"readerReadings"})), ], "rust": [ Control("compiles", "use intellistream_datahub_sdk::timeseries::TimeSeries;\n" From 4b2d81175bc193a996f5e077ab57b9c10a58cfd1 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:48:52 +0200 Subject: [PATCH 04/14] docs(rust): Event::new takes all three required fields, and a Node's id is a method MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `Event::new(external_id, r#type, event_time)` takes three arguments, and the struct's `r#type` and `event_time` are plain values rather than `Option`s — the field's own doc comment says why: the server rejects an event with no type, so there is no useful default. 27 pages passed the external id alone and then assigned `Some(...)` to both. `docs/reference/events.md` already had it right and is the shape they now follow. `Node::external_id(&self) -> &str` is a method, not a field, and the `&str` it returns needs no `.as_str()`. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/sustained-alarm-window.mdx | 6 +++--- docs/industries/agriculture-food/salmon-farming.mdx | 7 ++++--- docs/industries/built-environment/construction.mdx | 7 ++++--- docs/industries/built-environment/smart-buildings.mdx | 7 ++++--- docs/industries/energy-utilities/ev-charging.mdx | 7 ++++--- docs/industries/energy-utilities/grid.mdx | 7 ++++--- docs/industries/energy-utilities/waste.mdx | 7 ++++--- docs/industries/energy-utilities/water.mdx | 4 ++-- docs/industries/financial-services/aml.mdx | 4 ++-- .../industries/financial-services/insurance-fraud.mdx | 4 ++-- docs/industries/financial-services/portfolio-risk.mdx | 7 ++++--- docs/industries/healthcare/cold-chain.mdx | 7 ++++--- docs/industries/healthcare/hospital-operations.mdx | 7 ++++--- docs/industries/healthcare/medical-devices.mdx | 4 ++-- docs/industries/healthcare/patient-flow.mdx | 7 ++++--- docs/industries/manufacturing-process/discrete.mdx | 7 ++++--- docs/industries/manufacturing-process/pharma.mdx | 4 ++-- .../manufacturing-process/semiconductor.mdx | 4 ++-- docs/industries/mining-metals/operations.mdx | 7 ++++--- docs/industries/mining-metals/processing-plant.mdx | 7 ++++--- docs/industries/mining-metals/tailings-safety.mdx | 7 ++++--- docs/industries/oil-and-gas/drilling.mdx | 7 ++++--- docs/industries/oil-and-gas/emissions.mdx | 7 ++++--- docs/industries/oil-and-gas/pipeline.mdx | 11 ++++++----- docs/industries/oil-and-gas/production.mdx | 11 ++++++----- docs/industries/oil-and-gas/refining.mdx | 7 ++++--- docs/industries/oil-and-gas/storage.mdx | 7 ++++--- .../industries/technology-operations/data-centers.mdx | 11 ++++++----- docs/industries/technology-operations/network.mdx | 4 ++-- .../technology-operations/observability.mdx | 11 ++++++----- docs/industries/transport-logistics/aerospace.mdx | 4 ++-- docs/industries/transport-logistics/airports.mdx | 7 ++++--- docs/industries/transport-logistics/last-mile.mdx | 7 ++++--- docs/industries/transport-logistics/maritime.mdx | 7 ++++--- docs/industries/transport-logistics/ports.mdx | 7 ++++--- docs/industries/transport-logistics/rail.mdx | 2 +- docs/industries/transport-logistics/supply-chain.mdx | 8 ++++---- 37 files changed, 136 insertions(+), 110 deletions(-) diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index 76de57f..3113353 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -213,10 +213,10 @@ impl SustainedHigh { let peak = self.recent.iter().map(|(_, v)| *v).fold(f64::MIN, f64::max); let mut event = Event::new( - format!("sustained_high_{}_{}", self.series_id, at.timestamp())); - event.r#type = Some("sustained_high".into()); + format!("sustained_high_{}_{}", self.series_id, at.timestamp()), + "sustained_high".into(), + at); event.status = Some("open".into()); - event.set_event_time(at); event.add_metadata("series".into(), self.series_id.clone()); event.add_metadata("limit".into(), LIMIT.to_string()); event.add_metadata("window_minutes".into(), "20".into()); diff --git a/docs/industries/agriculture-food/salmon-farming.mdx b/docs/industries/agriculture-food/salmon-farming.mdx index 11dc209..220b532 100644 --- a/docs/industries/agriculture-food/salmon-farming.mdx +++ b/docs/industries/agriculture-food/salmon-farming.mdx @@ -92,12 +92,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["farm_hardanger_pens"]).await?; while let Some(Ok(msg)) = listener.next().await { if oxygen_below(&msg.payload, 6.0) { // mg/L — danger approaching - let mut alarm = Event::new(format!("low_oxygen_h07_{}", Utc::now().timestamp())); - alarm.r#type = Some("low_oxygen".into()); + let mut alarm = Event::new( + format!("low_oxygen_h07_{}", Utc::now().timestamp()), + "low_oxygen".into(), + Utc::now()); alarm.status = Some("critical".into()); alarm.add_metadata("pen".into(), "pen_h_07".into()); alarm.add_metadata("do_mg_l".into(), "5.6".into()); - alarm.set_event_time(Utc::now()); api.events.create(&vec![alarm]).await?; // triggers aeration } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/built-environment/construction.mdx b/docs/industries/built-environment/construction.mdx index d054972..3ecd281 100644 --- a/docs/industries/built-environment/construction.mdx +++ b/docs/industries/built-environment/construction.mdx @@ -159,13 +159,14 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut incident = Event::new(format!("safety_incident_l12_{}", Utc::now().timestamp())); -incident.r#type = Some("safety_incident".into()); +let mut incident = Event::new( + format!("safety_incident_l12_{}", Utc::now().timestamp()), + "safety_incident".into(), + Utc::now()); incident.sub_type = Some("near_miss".into()); incident.status = Some("open".into()); incident.add_metadata("zone".into(), "zone_level_12".into()); incident.add_metadata("category".into(), "dropped_object".into()); -incident.set_event_time(Utc::now()); api.events.create(&vec![incident]).await?; ``` diff --git a/docs/industries/built-environment/smart-buildings.mdx b/docs/industries/built-environment/smart-buildings.mdx index dbce800..e32900b 100644 --- a/docs/industries/built-environment/smart-buildings.mdx +++ b/docs/industries/built-environment/smart-buildings.mdx @@ -92,12 +92,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["tower_a_comfort"]).await?; while let Some(Ok(msg)) = listener.next().await { if outside_comfort(&msg.payload) { // temp or CO2 out of band - let mut alert = Event::new(format!("comfort_alert_l8_{}", Utc::now().timestamp())); - alert.r#type = Some("comfort_alert".into()); + let mut alert = Event::new( + format!("comfort_alert_l8_{}", Utc::now().timestamp()), + "comfort_alert".into(), + Utc::now()); alert.status = Some("open".into()); alert.add_metadata("zone".into(), "zone_l8_open_plan".into()); alert.add_metadata("co2_ppm".into(), "1180".into()); - alert.set_event_time(Utc::now()); api.events.create(&vec![alert]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/energy-utilities/ev-charging.mdx b/docs/industries/energy-utilities/ev-charging.mdx index c21d84d..dab3e70 100644 --- a/docs/industries/energy-utilities/ev-charging.mdx +++ b/docs/industries/energy-utilities/ev-charging.mdx @@ -87,12 +87,13 @@ use intellistream_datahub_sdk::events::Event; let mut listener = api.subscriptions.listen(&["network_status"]).await?; while let Some(Ok(msg)) = listener.next().await { if faulted(&msg.payload) { - let mut down = Event::new(format!("charger_down_oslo_14_{}", Utc::now().timestamp())); - down.r#type = Some("charger_down".into()); + let mut down = Event::new( + format!("charger_down_oslo_14_{}", Utc::now().timestamp()), + "charger_down".into(), + Utc::now()); down.status = Some("open".into()); down.add_metadata("charger".into(), "charger_oslo_14".into()); down.add_metadata("connector".into(), "2".into()); - down.set_event_time(Utc::now()); api.events.create(&vec![down]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index 642ae32..fa07540 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -198,13 +198,14 @@ client.events.create([intellistream_datahub_sdk.Event( ```rust use chrono::Utc; -let mut event = Event::new(format!("feeder_overload_f12_{}", Utc::now().timestamp())); -event.r#type = Some("feeder_overload".into()); +let mut event = Event::new( + format!("feeder_overload_f12_{}", Utc::now().timestamp()), + "feeder_overload".into(), + Utc::now()); event.status = Some("open".into()); event.add_metadata("feeder".into(), "feeder_f12".into()); event.add_metadata("peak_mw".into(), "14.8".into()); event.add_metadata("rating_mw".into(), "12.0".into()); -event.set_event_time(Utc::now()); api.events.create(&vec![event]).await?; ``` diff --git a/docs/industries/energy-utilities/waste.mdx b/docs/industries/energy-utilities/waste.mdx index 9527ed5..5e10696 100644 --- a/docs/industries/energy-utilities/waste.mdx +++ b/docs/industries/energy-utilities/waste.mdx @@ -80,12 +80,13 @@ let points = api.time_series.retrieve_datapoints(&last_reading("bin_grunerlokka_ .get_items().remove(0); let fill: f64 = points.datapoints[0].value.as_deref().unwrap_or("0").parse().unwrap_or(0.0); if fill >= 80.0 { - let mut due = Event::new(format!("collection_due_114_{}", Utc::now().timestamp())); - due.r#type = Some("collection_due".into()); + let mut due = Event::new( + format!("collection_due_114_{}", Utc::now().timestamp()), + "collection_due".into(), + points.datapoints[0].timestamp); due.status = Some("open".into()); due.add_metadata("bin".into(), "bin_grunerlokka_114".into()); due.add_metadata("fill_pct".into(), fill.to_string()); - due.set_event_time(points.datapoints[0].timestamp); api.events.create(&vec![due]).await?; } ``` diff --git a/docs/industries/energy-utilities/water.mdx b/docs/industries/energy-utilities/water.mdx index 1597bc9..148bce2 100644 --- a/docs/industries/energy-utilities/water.mdx +++ b/docs/industries/energy-utilities/water.mdx @@ -131,9 +131,9 @@ let west = api.resources.fetch_related( let east = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("zone_east_07").with_depth(20)).await?; -let w: HashSet<&str> = west.nodes().iter().map(|n| n.external_id.as_str()).collect(); +let w: HashSet<&str> = west.nodes().iter().map(|n| n.external_id()).collect(); let common: Vec<&str> = east.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| w.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| w.contains(id)).collect(); // common holds "main_trunk_north" → isolate there ``` diff --git a/docs/industries/financial-services/aml.mdx b/docs/industries/financial-services/aml.mdx index 2936ad7..0c77454 100644 --- a/docs/industries/financial-services/aml.mdx +++ b/docs/industries/financial-services/aml.mdx @@ -122,8 +122,8 @@ let ring = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("account_77310").with_depth(5)).await?; for node in ring.nodes() { - if node.external_id.starts_with("account_") { - println!("linked account: {}", node.external_id); + if node.external_id().starts_with("account_") { + println!("linked account: {}", node.external_id()); } } ``` diff --git a/docs/industries/financial-services/insurance-fraud.mdx b/docs/industries/financial-services/insurance-fraud.mdx index 5f35510..81a4622 100644 --- a/docs/industries/financial-services/insurance-fraud.mdx +++ b/docs/industries/financial-services/insurance-fraud.mdx @@ -129,8 +129,8 @@ let ring = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("claim_88421").with_depth(4)).await?; for node in ring.nodes() { - if node.external_id.starts_with("claim_") && node.external_id != "claim_88421" { - println!("linked claim: {}", node.external_id); + if node.external_id().starts_with("claim_") && node.external_id() != "claim_88421" { + println!("linked claim: {}", node.external_id()); } } ``` diff --git a/docs/industries/financial-services/portfolio-risk.mdx b/docs/industries/financial-services/portfolio-risk.mdx index a83f130..ef1557a 100644 --- a/docs/industries/financial-services/portfolio-risk.mdx +++ b/docs/industries/financial-services/portfolio-risk.mdx @@ -174,14 +174,15 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut breach = Event::new(format!("var_limit_breach_growth_{}", Utc::now().timestamp())); -breach.r#type = Some("var_limit_breach".into()); +let mut breach = Event::new( + format!("var_limit_breach_growth_{}", Utc::now().timestamp()), + "var_limit_breach".into(), + Utc::now()); breach.status = Some("open".into()); breach.data_set_id = desk_id; breach.add_metadata("portfolio".into(), "portfolio_growth".into()); breach.add_metadata("var_1d_usd".into(), "512340".into()); breach.add_metadata("limit_usd".into(), "500000".into()); -breach.set_event_time(Utc::now()); api.events.create(&vec![breach]).await?; ``` diff --git a/docs/industries/healthcare/cold-chain.mdx b/docs/industries/healthcare/cold-chain.mdx index 5b729c3..52f7b07 100644 --- a/docs/industries/healthcare/cold-chain.mdx +++ b/docs/industries/healthcare/cold-chain.mdx @@ -88,12 +88,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["pharmacy_fridges"]).await?; while let Some(Ok(msg)) = listener.next().await { if out_of_band(&msg.payload, 2.0, 8.0) { // °C — vaccine fridge band - let mut excursion = Event::new(format!("cold_chain_excursion_f12_{}", Utc::now().timestamp())); - excursion.r#type = Some("cold_chain_excursion".into()); + let mut excursion = Event::new( + format!("cold_chain_excursion_f12_{}", Utc::now().timestamp()), + "cold_chain_excursion".into(), + Utc::now()); excursion.status = Some("critical".into()); excursion.add_metadata("fridge".into(), "fridge_pharmacy_12".into()); excursion.add_metadata("temp_c".into(), "9.3".into()); - excursion.set_event_time(Utc::now()); api.events.create(&vec![excursion]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/healthcare/hospital-operations.mdx b/docs/industries/healthcare/hospital-operations.mdx index c6b6992..03bfa79 100644 --- a/docs/industries/healthcare/hospital-operations.mdx +++ b/docs/industries/healthcare/hospital-operations.mdx @@ -161,12 +161,13 @@ let mut listener = api.subscriptions.listen(&["bed_capacity"]).await?; while let Some(Ok(msg)) = listener.next().await { update_wallboard(&msg.payload); if over_threshold(&msg.payload) { // e.g. occupancy > 95% - let mut warning = Event::new(format!("capacity_warning_icu_{}", Utc::now().timestamp())); - warning.r#type = Some("capacity_warning".into()); + let mut warning = Event::new( + format!("capacity_warning_icu_{}", Utc::now().timestamp()), + "capacity_warning".into(), + Utc::now()); warning.status = Some("open".into()); warning.add_metadata("ward".into(), "ward_icu".into()); warning.add_metadata("occupancy_pct".into(), "96".into()); - warning.set_event_time(Utc::now()); api.events.create(&vec![warning]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/healthcare/medical-devices.mdx b/docs/industries/healthcare/medical-devices.mdx index 181f5a1..20b55bd 100644 --- a/docs/industries/healthcare/medical-devices.mdx +++ b/docs/industries/healthcare/medical-devices.mdx @@ -138,8 +138,8 @@ let affected = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("model_acme_x200").with_depth(3)).await?; for node in affected.nodes() { - if node.external_id.starts_with("pump_") { - println!("pull from service: {}", node.external_id); + if node.external_id().starts_with("pump_") { + println!("pull from service: {}", node.external_id()); } } ``` diff --git a/docs/industries/healthcare/patient-flow.mdx b/docs/industries/healthcare/patient-flow.mdx index 8af8926..4a79a79 100644 --- a/docs/industries/healthcare/patient-flow.mdx +++ b/docs/industries/healthcare/patient-flow.mdx @@ -133,12 +133,13 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut breach = Event::new(format!("flow_breach_ed_{}", Utc::now().timestamp())); -breach.r#type = Some("flow_breach".into()); +let mut breach = Event::new( + format!("flow_breach_ed_{}", Utc::now().timestamp()), + "flow_breach".into(), + Utc::now()); breach.status = Some("open".into()); breach.add_metadata("stage".into(), "emergency_department".into()); breach.add_metadata("breach_rate_pct".into(), "22".into()); -breach.set_event_time(Utc::now()); api.events.create(&vec![breach]).await?; ``` diff --git a/docs/industries/manufacturing-process/discrete.mdx b/docs/industries/manufacturing-process/discrete.mdx index 17fc295..7020c3f 100644 --- a/docs/industries/manufacturing-process/discrete.mdx +++ b/docs/industries/manufacturing-process/discrete.mdx @@ -197,13 +197,14 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut excursion = Event::new(format!("scrap_excursion_st07_{}", Utc::now().timestamp())); -excursion.r#type = Some("scrap_excursion".into()); +let mut excursion = Event::new( + format!("scrap_excursion_st07_{}", Utc::now().timestamp()), + "scrap_excursion".into(), + Utc::now()); excursion.status = Some("open".into()); excursion.add_metadata("station".into(), "station_07".into()); excursion.add_metadata("scrap_rate_pct".into(), "4.8".into()); excursion.add_metadata("limit_pct".into(), "2.0".into()); -excursion.set_event_time(Utc::now()); api.events.create(&vec![excursion]).await?; ``` diff --git a/docs/industries/manufacturing-process/pharma.mdx b/docs/industries/manufacturing-process/pharma.mdx index c68f246..6ea63f4 100644 --- a/docs/industries/manufacturing-process/pharma.mdx +++ b/docs/industries/manufacturing-process/pharma.mdx @@ -140,8 +140,8 @@ let lineage = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("lot_22f_final").with_depth(10)).await?; for node in lineage.nodes() { - if node.external_id.starts_with("lot_raw_") { - println!("raw material: {}", node.external_id); + if node.external_id().starts_with("lot_raw_") { + println!("raw material: {}", node.external_id()); } } ``` diff --git a/docs/industries/manufacturing-process/semiconductor.mdx b/docs/industries/manufacturing-process/semiconductor.mdx index b1577af..7c3a14b 100644 --- a/docs/industries/manufacturing-process/semiconductor.mdx +++ b/docs/industries/manufacturing-process/semiconductor.mdx @@ -140,9 +140,9 @@ let lot_b = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("lot_22863").with_depth(6)).await?; let tools_a: HashSet<&str> = lot_a.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| id.starts_with("tool_")).collect(); + .map(|n| n.external_id()).filter(|id| id.starts_with("tool_")).collect(); let suspect: Vec<&str> = lot_b.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| tools_a.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| tools_a.contains(id)).collect(); // suspect contains "tool_etch_07" ``` diff --git a/docs/industries/mining-metals/operations.mdx b/docs/industries/mining-metals/operations.mdx index 31f9230..e391e24 100644 --- a/docs/industries/mining-metals/operations.mdx +++ b/docs/industries/mining-metals/operations.mdx @@ -85,12 +85,13 @@ let points = api.time_series.retrieve_datapoints(&last_hour("truck_785_oil_press let low = points.datapoints.iter() .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(999.0) < 250.0); if low { - let mut warning = Event::new(format!("equipment_warning_785_{}", Utc::now().timestamp())); - warning.r#type = Some("equipment_warning".into()); + let mut warning = Event::new( + format!("equipment_warning_785_{}", Utc::now().timestamp()), + "equipment_warning".into(), + Utc::now()); warning.status = Some("open".into()); warning.add_metadata("unit".into(), "truck_785".into()); warning.add_metadata("signal".into(), "oil_pressure".into()); - warning.set_event_time(Utc::now()); api.events.create(&vec![warning]).await?; } ``` diff --git a/docs/industries/mining-metals/processing-plant.mdx b/docs/industries/mining-metals/processing-plant.mdx index f2c6264..e81741b 100644 --- a/docs/industries/mining-metals/processing-plant.mdx +++ b/docs/industries/mining-metals/processing-plant.mdx @@ -134,13 +134,14 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut loss = Event::new(format!("recovery_loss_mill1_{}", Utc::now().timestamp())); -loss.r#type = Some("recovery_loss".into()); +let mut loss = Event::new( + format!("recovery_loss_mill1_{}", Utc::now().timestamp()), + "recovery_loss".into(), + Utc::now()); loss.status = Some("open".into()); loss.add_metadata("mill".into(), "mill_1".into()); loss.add_metadata("recovery_pct".into(), "88.4".into()); loss.add_metadata("target_pct".into(), "91.0".into()); -loss.set_event_time(Utc::now()); api.events.create(&vec![loss]).await?; ``` diff --git a/docs/industries/mining-metals/tailings-safety.mdx b/docs/industries/mining-metals/tailings-safety.mdx index eeb349b..2f1cdaa 100644 --- a/docs/industries/mining-metals/tailings-safety.mdx +++ b/docs/industries/mining-metals/tailings-safety.mdx @@ -95,13 +95,14 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["tsf_instruments"]).await?; while let Some(Ok(msg)) = listener.next().await { if let Some(level) = trigger_level(&msg.payload) { // "amber" | "red" - let mut alarm = Event::new(format!("tailings_alarm_p14_{}", Utc::now().timestamp())); - alarm.r#type = Some("tailings_alarm".into()); + let mut alarm = Event::new( + format!("tailings_alarm_p14_{}", Utc::now().timestamp()), + "tailings_alarm".into(), + Utc::now()); alarm.status = Some(if level == "red" { "critical" } else { "warning" }.into()); alarm.add_metadata("instrument".into(), "piezometer_p14".into()); alarm.add_metadata("level".into(), level.into()); alarm.add_metadata("pore_pressure_kpa".into(), "186".into()); - alarm.set_event_time(Utc::now()); api.events.create(&vec![alarm]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/oil-and-gas/drilling.mdx b/docs/industries/oil-and-gas/drilling.mdx index 2a17094..6eace09 100644 --- a/docs/industries/oil-and-gas/drilling.mdx +++ b/docs/industries/oil-and-gas/drilling.mdx @@ -100,13 +100,14 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["rig_deepwater_1"]).await?; while let Some(Ok(msg)) = listener.next().await { if influx_detected(&msg.payload) { // flow_out > flow_in & pit rising - let mut kick = Event::new(format!("kick_detected_a12_{}", Utc::now().timestamp())); - kick.r#type = Some("kick_detected".into()); + let mut kick = Event::new( + format!("kick_detected_a12_{}", Utc::now().timestamp()), + "kick_detected".into(), + Utc::now()); kick.status = Some("critical".into()); kick.add_metadata("well".into(), "well_a12".into()); kick.add_metadata("rig".into(), "rig_deepwater_1".into()); kick.add_metadata("flow_delta_gpm".into(), "18".into()); - kick.set_event_time(Utc::now()); api.events.create(&vec![kick]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/oil-and-gas/emissions.mdx b/docs/industries/oil-and-gas/emissions.mdx index 8177c85..ede6b26 100644 --- a/docs/industries/oil-and-gas/emissions.mdx +++ b/docs/industries/oil-and-gas/emissions.mdx @@ -135,13 +135,14 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut exceedance = Event::new(format!("flaring_exceedance_north_{}", Utc::now().timestamp())); -exceedance.r#type = Some("flaring_exceedance".into()); +let mut exceedance = Event::new( + format!("flaring_exceedance_north_{}", Utc::now().timestamp()), + "flaring_exceedance".into(), + Utc::now()); exceedance.status = Some("open".into()); exceedance.add_metadata("site".into(), "platform_north".into()); exceedance.add_metadata("flared_m3".into(), "142000".into()); exceedance.add_metadata("permit_m3".into(), "120000".into()); -exceedance.set_event_time(Utc::now()); api.events.create(&vec![exceedance]).await?; ``` diff --git a/docs/industries/oil-and-gas/pipeline.mdx b/docs/industries/oil-and-gas/pipeline.mdx index bef91cf..ff03527 100644 --- a/docs/industries/oil-and-gas/pipeline.mdx +++ b/docs/industries/oil-and-gas/pipeline.mdx @@ -96,12 +96,13 @@ let inflow = latest("segment_pn_07_flow_in_m3h").await?; let outflow = latest("segment_pn_07_flow_out_m3h").await?; if inflow - outflow > tolerance(inflow) { - let mut leak = Event::new(format!("leak_suspected_pn07_{}", Utc::now().timestamp())); - leak.r#type = Some("leak_suspected".into()); + let mut leak = Event::new( + format!("leak_suspected_pn07_{}", Utc::now().timestamp()), + "leak_suspected".into(), + Utc::now()); leak.status = Some("critical".into()); leak.add_metadata("segment".into(), "segment_pn_07".into()); leak.add_metadata("imbalance_m3h".into(), (inflow - outflow).to_string()); - leak.set_event_time(Utc::now()); api.events.create(&vec![leak]).await?; } ``` @@ -155,8 +156,8 @@ let around = api.resources.fetch_related( .with_relationship_types(vec!["connects_to".into(), "isolated_by".into()])).await?; for node in around.nodes() { - if node.external_id.starts_with("valve_") { - println!("close: {}", node.external_id); + if node.external_id().starts_with("valve_") { + println!("close: {}", node.external_id()); } } ``` diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 1f94d9b..3778eda 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -236,12 +236,13 @@ let points = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressur let low = points.datapoints.iter() .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(99.0) < 80.0); if low { - let mut event = Event::new(format!("esp_anomaly_a12_{}", Utc::now().timestamp())); - event.r#type = Some("esp_anomaly".into()); + let mut event = Event::new( + format!("esp_anomaly_a12_{}", Utc::now().timestamp()), + "esp_anomaly".into(), + Utc::now()); event.status = Some("open".into()); event.add_metadata("well".into(), "well_a12".into()); event.add_metadata("pump".into(), "pump_esp_a12".into()); - event.set_event_time(Utc::now()); api.events.create(&vec![event]).await?; } ``` @@ -295,9 +296,9 @@ let na = api.resources.fetch_related( let nb = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("pump_temp_a12").with_depth(5)).await?; -let a: HashSet<&str> = na.nodes().iter().map(|n| n.external_id.as_str()).collect(); +let a: HashSet<&str> = na.nodes().iter().map(|n| n.external_id()).collect(); let shared: Vec<&str> = nb.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| a.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| a.contains(id)).collect(); // shared contains "cooling_system" → one root cause, not two ``` diff --git a/docs/industries/oil-and-gas/refining.mdx b/docs/industries/oil-and-gas/refining.mdx index 5149a42..4e6c3d4 100644 --- a/docs/industries/oil-and-gas/refining.mdx +++ b/docs/industries/oil-and-gas/refining.mdx @@ -134,13 +134,14 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut upset = Event::new(format!("process_upset_cdu1_{}", Utc::now().timestamp())); -upset.r#type = Some("process_upset".into()); +let mut upset = Event::new( + format!("process_upset_cdu1_{}", Utc::now().timestamp()), + "process_upset".into(), + Utc::now()); upset.status = Some("open".into()); upset.add_metadata("unit".into(), "crude_unit_1".into()); upset.add_metadata("tag".into(), "column_top_temp".into()); upset.add_metadata("value_c".into(), "168".into()); -upset.set_event_time(Utc::now()); api.events.create(&vec![upset]).await?; ``` diff --git a/docs/industries/oil-and-gas/storage.mdx b/docs/industries/oil-and-gas/storage.mdx index f54f2ac..77541ca 100644 --- a/docs/industries/oil-and-gas/storage.mdx +++ b/docs/industries/oil-and-gas/storage.mdx @@ -103,12 +103,13 @@ let metered = sum_over("tank_t_12_receipts_bbl", shift_start).await? let unexplained = measured_change - metered; if unexplained.abs() > tolerance(latest("tank_t_12_volume_bbl").await?) { - let mut loss = Event::new(format!("inventory_discrepancy_t12_{}", Utc::now().timestamp())); - loss.r#type = Some("inventory_discrepancy".into()); + let mut loss = Event::new( + format!("inventory_discrepancy_t12_{}", Utc::now().timestamp()), + "inventory_discrepancy".into(), + shift_start); loss.status = Some("open".into()); loss.add_metadata("tank".into(), "tank_t_12".into()); loss.add_metadata("unexplained_bbl".into(), format!("{:.1}", unexplained)); - loss.set_event_time(shift_start); api.events.create(&vec![loss]).await?; } ``` diff --git a/docs/industries/technology-operations/data-centers.mdx b/docs/industries/technology-operations/data-centers.mdx index ab9f332..392338c 100644 --- a/docs/industries/technology-operations/data-centers.mdx +++ b/docs/industries/technology-operations/data-centers.mdx @@ -94,12 +94,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["hall_2_thermal"]).await?; while let Some(Ok(msg)) = listener.next().await { if inlet_above(&msg.payload, 27.0) { // °C — above ASHRAE band - let mut warning = Event::new(format!("thermal_warning_r14_{}", Utc::now().timestamp())); - warning.r#type = Some("thermal_warning".into()); + let mut warning = Event::new( + format!("thermal_warning_r14_{}", Utc::now().timestamp()), + "thermal_warning".into(), + Utc::now()); warning.status = Some("open".into()); warning.add_metadata("rack".into(), "rack_r14".into()); warning.add_metadata("inlet_c".into(), "29.4".into()); - warning.set_event_time(Utc::now()); api.events.create(&vec![warning]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; @@ -156,9 +157,9 @@ let a = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("rack_r14").with_depth(3)).await?; let b = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("rack_r15").with_depth(3)).await?; -let an: HashSet<&str> = a.nodes().iter().map(|n| n.external_id.as_str()).collect(); +let an: HashSet<&str> = a.nodes().iter().map(|n| n.external_id()).collect(); let shared: Vec<&str> = b.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| an.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| an.contains(id)).collect(); // shared contains "crac_unit_2" ``` diff --git a/docs/industries/technology-operations/network.mdx b/docs/industries/technology-operations/network.mdx index 0838e6c..521897d 100644 --- a/docs/industries/technology-operations/network.mdx +++ b/docs/industries/technology-operations/network.mdx @@ -149,9 +149,9 @@ let c1 = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("cell_oslo_4412").with_depth(4)).await?; let c2 = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("cell_oslo_4418").with_depth(4)).await?; -let n1: HashSet<&str> = c1.nodes().iter().map(|n| n.external_id.as_str()).collect(); +let n1: HashSet<&str> = c1.nodes().iter().map(|n| n.external_id()).collect(); let shared: Vec<&str> = c2.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| n1.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| n1.contains(id)).collect(); // shared contains "backhaul_link_88" ``` diff --git a/docs/industries/technology-operations/observability.mdx b/docs/industries/technology-operations/observability.mdx index b72ecd2..ccc2f79 100644 --- a/docs/industries/technology-operations/observability.mdx +++ b/docs/industries/technology-operations/observability.mdx @@ -164,12 +164,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["checkout_slo"]).await?; while let Some(Ok(msg)) = listener.next().await { if breaches_slo(&msg.payload) { // e.g. p99 latency > 300 ms - let mut event = Event::new(format!("slo_breach_checkout_{}", Utc::now().timestamp())); - event.r#type = Some("slo_breach".into()); + let mut event = Event::new( + format!("slo_breach_checkout_{}", Utc::now().timestamp()), + "slo_breach".into(), + Utc::now()); event.status = Some("firing".into()); event.add_metadata("service".into(), "service_checkout".into()); event.add_metadata("slo".into(), "latency_p99".into()); - event.set_event_time(Utc::now()); api.events.create(&vec![event]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; @@ -266,9 +267,9 @@ let checkout = api.resources.fetch_related( let payments = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("service_payments").with_depth(4)).await?; -let deps: HashSet<&str> = checkout.nodes().iter().map(|n| n.external_id.as_str()).collect(); +let deps: HashSet<&str> = checkout.nodes().iter().map(|n| n.external_id()).collect(); let shared: Vec<&str> = payments.nodes().iter() - .map(|n| n.external_id.as_str()).filter(|id| deps.contains(id)).collect(); + .map(|n| n.external_id()).filter(|id| deps.contains(id)).collect(); // shared contains "order_db" → one failing dependency, not two outages ``` diff --git a/docs/industries/transport-logistics/aerospace.mdx b/docs/industries/transport-logistics/aerospace.mdx index 53735a5..75276ec 100644 --- a/docs/industries/transport-logistics/aerospace.mdx +++ b/docs/industries/transport-logistics/aerospace.mdx @@ -156,8 +156,8 @@ let affected = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("part_type_hp_47").with_depth(3)).await?; for node in affected.nodes() { - if node.external_id.starts_with("aircraft_") { - println!("inspect: {}", node.external_id); + if node.external_id().starts_with("aircraft_") { + println!("inspect: {}", node.external_id()); } } ``` diff --git a/docs/industries/transport-logistics/airports.mdx b/docs/industries/transport-logistics/airports.mdx index 113ad48..8cbd0ca 100644 --- a/docs/industries/transport-logistics/airports.mdx +++ b/docs/industries/transport-logistics/airports.mdx @@ -86,13 +86,14 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["stand_b12_turnaround"]).await?; while let Some(Ok(msg)) = listener.next().await { if leg_overrunning(&msg.payload) { // e.g. fuelling past plan - let mut risk = Event::new(format!("turnaround_risk_su204_{}", Utc::now().timestamp())); - risk.r#type = Some("turnaround_risk".into()); + let mut risk = Event::new( + format!("turnaround_risk_su204_{}", Utc::now().timestamp()), + "turnaround_risk".into(), + Utc::now()); risk.status = Some("open".into()); risk.add_metadata("flight".into(), "flight_su204".into()); risk.add_metadata("leg".into(), "fuelling".into()); risk.add_metadata("stand".into(), "stand_b12".into()); - risk.set_event_time(Utc::now()); api.events.create(&vec![risk]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/transport-logistics/last-mile.mdx b/docs/industries/transport-logistics/last-mile.mdx index f130837..b3df15a 100644 --- a/docs/industries/transport-logistics/last-mile.mdx +++ b/docs/industries/transport-logistics/last-mile.mdx @@ -84,13 +84,14 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["fleet_eta"]).await?; while let Some(Ok(msg)) = listener.next().await { if eta_past_window(&msg.payload) { - let mut risk = Event::new(format!("delivery_at_risk_v22_{}", Utc::now().timestamp())); - risk.r#type = Some("delivery_at_risk".into()); + let mut risk = Event::new( + format!("delivery_at_risk_v22_{}", Utc::now().timestamp()), + "delivery_at_risk".into(), + Utc::now()); risk.status = Some("open".into()); risk.add_metadata("van".into(), "van_22".into()); risk.add_metadata("route".into(), "route_oslo_e".into()); risk.add_metadata("stops_left".into(), "9".into()); - risk.set_event_time(Utc::now()); api.events.create(&vec![risk]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/transport-logistics/maritime.mdx b/docs/industries/transport-logistics/maritime.mdx index 6fd9d2c..8f677d9 100644 --- a/docs/industries/transport-logistics/maritime.mdx +++ b/docs/industries/transport-logistics/maritime.mdx @@ -134,12 +134,13 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["reefer_fleet"]).await?; while let Some(Ok(msg)) = listener.next().await { if out_of_band(&msg.payload) { // |supply - setpoint| > tolerance - let mut excursion = Event::new(format!("reefer_excursion_1182_{}", Utc::now().timestamp())); - excursion.r#type = Some("reefer_excursion".into()); + let mut excursion = Event::new( + format!("reefer_excursion_1182_{}", Utc::now().timestamp()), + "reefer_excursion".into(), + Utc::now()); excursion.status = Some("open".into()); excursion.add_metadata("reefer".into(), "reefer_msc_1182".into()); excursion.add_metadata("vessel".into(), "vessel_nordic_star".into()); - excursion.set_event_time(Utc::now()); api.events.create(&vec![excursion]).await?; } listener.ack(&[msg.message_id.as_str()]).await?; diff --git a/docs/industries/transport-logistics/ports.mdx b/docs/industries/transport-logistics/ports.mdx index 01a03ae..04ba83f 100644 --- a/docs/industries/transport-logistics/ports.mdx +++ b/docs/industries/transport-logistics/ports.mdx @@ -133,12 +133,13 @@ client.events.create([intellistream_datahub_sdk.Event( use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let mut congestion = Event::new(format!("yard_congestion_b07_{}", Utc::now().timestamp())); -congestion.r#type = Some("yard_congestion".into()); +let mut congestion = Event::new( + format!("yard_congestion_b07_{}", Utc::now().timestamp()), + "yard_congestion".into(), + Utc::now()); congestion.status = Some("open".into()); congestion.add_metadata("block".into(), "yard_block_b07".into()); congestion.add_metadata("occupancy_pct".into(), "94".into()); -congestion.set_event_time(Utc::now()); api.events.create(&vec![congestion]).await?; ``` diff --git a/docs/industries/transport-logistics/rail.mdx b/docs/industries/transport-logistics/rail.mdx index 61cfd82..fbb9cde 100644 --- a/docs/industries/transport-logistics/rail.mdx +++ b/docs/industries/transport-logistics/rail.mdx @@ -127,7 +127,7 @@ let reachable = api.resources.fetch_related( .with_relationship_types(vec!["connects_to".into()])).await?; let still_connected = reachable.nodes().iter() - .any(|n| n.external_id == "station_bergen_n"); + .any(|n| n.external_id() == "station_bergen_n"); println!("{}", if still_connected { "route open" } else { "SEVERED — reroute required" }); ``` diff --git a/docs/industries/transport-logistics/supply-chain.mdx b/docs/industries/transport-logistics/supply-chain.mdx index 354564a..2f83a62 100644 --- a/docs/industries/transport-logistics/supply-chain.mdx +++ b/docs/industries/transport-logistics/supply-chain.mdx @@ -137,11 +137,11 @@ let impacted = api.resources.fetch_related( &RelatedResourcesForm::from_external_id("lot_acme_8842").with_depth(10)).await?; for node in impacted.nodes() { - if node.external_id.starts_with("shipment_") { - println!("recall shipment: {}", node.external_id); + if node.external_id().starts_with("shipment_") { + println!("recall shipment: {}", node.external_id()); } - if node.external_id.starts_with("product_") { - println!("affected product: {}", node.external_id); + if node.external_id().starts_with("product_") { + println!("affected product: {}", node.external_id()); } } ``` From 5c95eac08f33bd01de66874060272bbe8ddf40a8 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:50:33 +0200 Subject: [PATCH 05/14] docs(rust): show the use lines the examples need MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Rust pages carry their own imports — nothing is supplied for them — and the tutorial's step blocks showed only the ones for building a client, so a reader following the steps had no `IdAndExtId`, `DataWrapper`, `TimeSeries`, `HashMap`, `System` or `Utc`. The complete programs at the end of the page already listed them; the steps now name what each one uses, by the same paths. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/sustained-alarm-window.mdx | 1 + docs/industries/energy-utilities/grid.mdx | 2 ++ docs/industries/oil-and-gas/production.mdx | 1 + docs/tutorial.mdx | 16 ++++++++++++++++ 4 files changed, 20 insertions(+) diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index 3113353..c88c167 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -163,6 +163,7 @@ class SustainedHigh: use chrono::{DateTime, Duration, Utc}; use intellistream_datahub_sdk::events::Event; use std::collections::VecDeque; +use intellistream_datahub_sdk::ApiService; const LIMIT: f64 = 4.5; const CLEAR_BELOW: f64 = 4.2; diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index fa07540..e51c575 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -145,6 +145,7 @@ for dp in client.timeseries.retrieve_datapoints(rf)[0].get_datapoints(): ```rust use chrono::Utc; +use intellistream_datahub_sdk::generic::{DataWrapper, RetrieveFilter}; let filter = RetrieveFilter { external_id: Some("feeder_f12_load_mw".into()), @@ -197,6 +198,7 @@ client.events.create([intellistream_datahub_sdk.Event( ```rust use chrono::Utc; +use intellistream_datahub_sdk::events::Event; let mut event = Event::new( format!("feeder_overload_f12_{}", Utc::now().timestamp()), diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 3778eda..28fd1fb 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -230,6 +230,7 @@ if any(float(dp.value) < 80.0 for dp in points.get_datapoints()): ```rust use chrono::Utc; +use intellistream_datahub_sdk::events::Event; let points = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressure_bar")).await? .get_items().remove(0); diff --git a/docs/tutorial.mdx b/docs/tutorial.mdx index 7a99fa4..89d7044 100644 --- a/docs/tutorial.mdx +++ b/docs/tutorial.mdx @@ -304,6 +304,9 @@ if missing: ```rust +use intellistream_datahub_sdk::generic::{DataWrapper, IdAndExtId}; +use intellistream_datahub_sdk::timeseries::TimeSeries; + let lookups: Vec = METRICS.iter() .map(|(base, _)| IdAndExtId::from_external_id(&format!("{base}_{host}"))) .collect(); @@ -328,6 +331,9 @@ for (base, name) in METRICS { ```rust +use intellistream_datahub_sdk::generic::{DataWrapper, IdAndExtId}; +use intellistream_datahub_sdk::timeseries::TimeSeries; + let lookups: Vec = METRICS.iter() .map(|(base, _)| IdAndExtId::from_external_id(&format!("{base}_{host}"))) .collect(); @@ -405,6 +411,9 @@ The sampler is plain synchronous code, identical in both Rust flavors. `sysinfo` exposes `used_memory()`/`available_memory()`/`used_swap()` directly: ```rust +use std::collections::HashMap; +use sysinfo::System; + fn sample() -> HashMap<&'static str, i64> { let mut sys = System::new(); sys.refresh_memory(); @@ -423,6 +432,9 @@ The sampler is plain synchronous code, identical in both Rust flavors. `sysinfo` exposes `used_memory()`/`available_memory()`/`used_swap()` directly: ```rust +use std::collections::HashMap; +use sysinfo::System; + fn sample() -> HashMap<&'static str, i64> { let mut sys = System::new(); sys.refresh_memory(); @@ -480,6 +492,8 @@ for base in METRICS: One `insert_datapoint` call per series: ```rust +use chrono::Utc; + let now = Utc::now(); let values = sample(); for (base, _) in METRICS { @@ -495,6 +509,8 @@ for (base, _) in METRICS { One `insert_datapoint` call per series: ```rust +use chrono::Utc; + let now = Utc::now(); let values = sample(); for (base, _) in METRICS { From e5675b515eeac8bac03a103365520b53afe1a874 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:56:28 +0200 Subject: [PATCH 06/14] docs(rust): unwrap a FileUpload, and take an item out of a DataWrapper mutably MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `FileUpload::new_with_destination_path` answers `io::Result` — it reads the file's metadata and refuses a directory — so the four pages that build one need `?` before they can set a field on it. `DataWrapper::get_items` lends the vector (`&Vec`); taking an item out of it needs `get_items_mut`. All 24 `get_items().remove(0)` reads were wrong, though only 10 were visible: rustc stops before the borrow checker on any unit that still has an unresolved name, so the rest were hidden behind other errors on their own pages. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/asset-health-score.mdx | 2 +- docs/advanced/demand-forecasting.mdx | 2 +- docs/advanced/kmeans-clustering.mdx | 2 +- docs/advanced/lstm-anomaly-detection.mdx | 2 +- docs/advanced/lstm-forecasting.mdx | 2 +- docs/advanced/pca-process-monitoring.mdx | 2 +- docs/advanced/predictive-maintenance.mdx | 2 +- docs/advanced/random-forest-soft-sensor.mdx | 2 +- docs/advanced/sustained-alarm-window.mdx | 2 +- docs/advanced/xgboost-failure-prediction.mdx | 2 +- docs/guides/attach-files.mdx | 2 +- docs/industries/agriculture-food/precision-farming.mdx | 2 +- docs/industries/built-environment/construction.mdx | 2 +- docs/industries/built-environment/smart-buildings.mdx | 2 +- docs/industries/energy-utilities/grid.mdx | 2 +- docs/industries/energy-utilities/waste.mdx | 2 +- docs/industries/energy-utilities/wind.mdx | 2 +- docs/industries/healthcare/patient-flow.mdx | 2 +- docs/industries/manufacturing-process/discrete.mdx | 2 +- docs/industries/mining-metals/operations.mdx | 4 ++-- docs/industries/mining-metals/processing-plant.mdx | 2 +- docs/industries/oil-and-gas/emissions.mdx | 2 +- docs/industries/oil-and-gas/production.mdx | 2 +- docs/industries/oil-and-gas/refining.mdx | 2 +- docs/industries/technology-operations/network.mdx | 2 +- docs/industries/transport-logistics/ports.mdx | 2 +- docs/reference/files.md | 2 +- 27 files changed, 28 insertions(+), 28 deletions(-) diff --git a/docs/advanced/asset-health-score.mdx b/docs/advanced/asset-health-score.mdx index 108f410..7c65003 100644 --- a/docs/advanced/asset-health-score.mdx +++ b/docs/advanced/asset-health-score.mdx @@ -84,7 +84,7 @@ use intellistream_datahub_sdk::generic::{DataWrapper, IdAndExtId}; let latest = api.time_series .retrieve_latest_datapoint(&DataWrapper::from(vec![ IdAndExtId::from_external_id("pump_07_bearing_temp_c")])).await? - .get_items().remove(0); + .get_items_mut().remove(0); let bearing_temp = latest.datapoints.last().and_then(|p| p.value).unwrap_or(f64::NAN); ``` diff --git a/docs/advanced/demand-forecasting.mdx b/docs/advanced/demand-forecasting.mdx index 250bea7..cb01c08 100644 --- a/docs/advanced/demand-forecasting.mdx +++ b/docs/advanced/demand-forecasting.mdx @@ -90,7 +90,7 @@ let filter = RetrieveFilter { }; let history = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/kmeans-clustering.mdx b/docs/advanced/kmeans-clustering.mdx index 3fe3111..7c09c30 100644 --- a/docs/advanced/kmeans-clustering.mdx +++ b/docs/advanced/kmeans-clustering.mdx @@ -99,7 +99,7 @@ let filter = RetrieveFilter { }; let sig = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/lstm-anomaly-detection.mdx b/docs/advanced/lstm-anomaly-detection.mdx index 0daa7cb..20e64c2 100644 --- a/docs/advanced/lstm-anomaly-detection.mdx +++ b/docs/advanced/lstm-anomaly-detection.mdx @@ -93,7 +93,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/lstm-forecasting.mdx b/docs/advanced/lstm-forecasting.mdx index 6c5ef90..0f45963 100644 --- a/docs/advanced/lstm-forecasting.mdx +++ b/docs/advanced/lstm-forecasting.mdx @@ -96,7 +96,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/pca-process-monitoring.mdx b/docs/advanced/pca-process-monitoring.mdx index 0da9de7..f2b8224 100644 --- a/docs/advanced/pca-process-monitoring.mdx +++ b/docs/advanced/pca-process-monitoring.mdx @@ -102,7 +102,7 @@ let filter = RetrieveFilter { }; let pts = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/predictive-maintenance.mdx b/docs/advanced/predictive-maintenance.mdx index 1e0f5e9..f34230e 100644 --- a/docs/advanced/predictive-maintenance.mdx +++ b/docs/advanced/predictive-maintenance.mdx @@ -93,7 +93,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/random-forest-soft-sensor.mdx b/docs/advanced/random-forest-soft-sensor.mdx index 77a596f..61c7445 100644 --- a/docs/advanced/random-forest-soft-sensor.mdx +++ b/docs/advanced/random-forest-soft-sensor.mdx @@ -96,7 +96,7 @@ let filter = RetrieveFilter { }; let pts = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index c88c167..0c2b05e 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -318,7 +318,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); let mut detector = SustainedHigh::new(SERIES); let (mut raised, mut crossings, mut previous) = (0, 0, 0.0_f64); diff --git a/docs/advanced/xgboost-failure-prediction.mdx b/docs/advanced/xgboost-failure-prediction.mdx index dc7d97b..bf10caa 100644 --- a/docs/advanced/xgboost-failure-prediction.mdx +++ b/docs/advanced/xgboost-failure-prediction.mdx @@ -97,7 +97,7 @@ let filter = RetrieveFilter { }; let agg = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); ``` diff --git a/docs/guides/attach-files.mdx b/docs/guides/attach-files.mdx index d6695cf..4a683dd 100644 --- a/docs/guides/attach-files.mdx +++ b/docs/guides/attach-files.mdx @@ -63,7 +63,7 @@ use intellistream_datahub_sdk::files::FileUpload; // MIME type is inferred from the file content let mut upload = FileUpload::new_with_destination_path( - "calibration_a12.pdf", "/certificates/2026/"); + "calibration_a12.pdf", "/certificates/2026/")?; upload.set_external_id("calibration_pump_esp_a12".into()); upload.set_file_name("calibration_a12.pdf".into()); upload.set_data_set_id(42); diff --git a/docs/industries/agriculture-food/precision-farming.mdx b/docs/industries/agriculture-food/precision-farming.mdx index 5bc0aa7..3de85e0 100644 --- a/docs/industries/agriculture-food/precision-farming.mdx +++ b/docs/industries/agriculture-food/precision-farming.mdx @@ -134,7 +134,7 @@ client.files.upload_file(intellistream_datahub_sdk.FileUpload( use intellistream_datahub_sdk::files::FileUpload; let mut upload = FileUpload::new_with_destination_path( - "north_40_2026_06_28.tif", "/fields/north_40/scans/"); + "north_40_2026_06_28.tif", "/fields/north_40/scans/")?; upload.external_id = "scan_north_40_2026_06_28".into(); upload.name = "2026_06_28.tif".into(); api.files.upload_file(upload).await?; diff --git a/docs/industries/built-environment/construction.mdx b/docs/industries/built-environment/construction.mdx index 3ecd281..ca2edf0 100644 --- a/docs/industries/built-environment/construction.mdx +++ b/docs/industries/built-environment/construction.mdx @@ -113,7 +113,7 @@ api.resources.create( vec![RelForm::by_external_ids("site_harbour_tower", "zone_level_12", "contains")]).await?; let mut upload = FileUpload::new_with_destination_path( - "level_12_rev_c.pdf", "/harbour_tower/level_12/drawings/"); + "level_12_rev_c.pdf", "/harbour_tower/level_12/drawings/")?; upload.external_id = "drawing_level_12_structural_rev_c".into(); upload.name = "structural_rev_c.pdf".into(); api.files.upload_file(upload).await?; diff --git a/docs/industries/built-environment/smart-buildings.mdx b/docs/industries/built-environment/smart-buildings.mdx index e32900b..7a6d26c 100644 --- a/docs/industries/built-environment/smart-buildings.mdx +++ b/docs/industries/built-environment/smart-buildings.mdx @@ -165,7 +165,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { chart_daily_kwh(&p.timestamp, p.sum); } ``` diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index e51c575..ae3cb8d 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -157,7 +157,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { chart(&p.timestamp, p.average, p.max); } ``` diff --git a/docs/industries/energy-utilities/waste.mdx b/docs/industries/energy-utilities/waste.mdx index 5e10696..34e624e 100644 --- a/docs/industries/energy-utilities/waste.mdx +++ b/docs/industries/energy-utilities/waste.mdx @@ -77,7 +77,7 @@ use chrono::Utc; use intellistream_datahub_sdk::events::Event; let points = api.time_series.retrieve_datapoints(&last_reading("bin_grunerlokka_114_fill_pct")).await? - .get_items().remove(0); + .get_items_mut().remove(0); let fill: f64 = points.datapoints[0].value.as_deref().unwrap_or("0").parse().unwrap_or(0.0); if fill >= 80.0 { let mut due = Event::new( diff --git a/docs/industries/energy-utilities/wind.mdx b/docs/industries/energy-utilities/wind.mdx index c8c337d..32e8bf1 100644 --- a/docs/industries/energy-utilities/wind.mdx +++ b/docs/industries/energy-utilities/wind.mdx @@ -167,7 +167,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); let rated = 3500.0; for p in &series.datapoints { if let Some(avg) = p.average { record_capacity_factor(&p.timestamp, avg / rated); } diff --git a/docs/industries/healthcare/patient-flow.mdx b/docs/industries/healthcare/patient-flow.mdx index 4a79a79..fadaa1c 100644 --- a/docs/industries/healthcare/patient-flow.mdx +++ b/docs/industries/healthcare/patient-flow.mdx @@ -89,7 +89,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { track_stage("time_to_bed", &p.timestamp, p.average); } ``` diff --git a/docs/industries/manufacturing-process/discrete.mdx b/docs/industries/manufacturing-process/discrete.mdx index 7020c3f..0f8860c 100644 --- a/docs/industries/manufacturing-process/discrete.mdx +++ b/docs/industries/manufacturing-process/discrete.mdx @@ -154,7 +154,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { record_hourly_performance(&p.timestamp, p.average); } ``` diff --git a/docs/industries/mining-metals/operations.mdx b/docs/industries/mining-metals/operations.mdx index e391e24..1ba37cc 100644 --- a/docs/industries/mining-metals/operations.mdx +++ b/docs/industries/mining-metals/operations.mdx @@ -81,7 +81,7 @@ use intellistream_datahub_sdk::events::Event; use chrono::Utc; let points = api.time_series.retrieve_datapoints(&last_hour("truck_785_oil_pressure_kpa")).await? - .get_items().remove(0); + .get_items_mut().remove(0); let low = points.datapoints.iter() .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(999.0) < 250.0); if low { @@ -156,7 +156,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { compare_to_plan(&p.timestamp, p.average); } ``` diff --git a/docs/industries/mining-metals/processing-plant.mdx b/docs/industries/mining-metals/processing-plant.mdx index e81741b..c1ac672 100644 --- a/docs/industries/mining-metals/processing-plant.mdx +++ b/docs/industries/mining-metals/processing-plant.mdx @@ -90,7 +90,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { compare_to_target(&p.timestamp, p.average); } ``` diff --git a/docs/industries/oil-and-gas/emissions.mdx b/docs/industries/oil-and-gas/emissions.mdx index ede6b26..f43ab7f 100644 --- a/docs/industries/oil-and-gas/emissions.mdx +++ b/docs/industries/oil-and-gas/emissions.mdx @@ -90,7 +90,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); let monthly: f64 = series.datapoints.iter() .filter_map(|p| p.sum).sum(); ``` diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 28fd1fb..56457c0 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -233,7 +233,7 @@ use chrono::Utc; use intellistream_datahub_sdk::events::Event; let points = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressure_bar")).await? - .get_items().remove(0); + .get_items_mut().remove(0); let low = points.datapoints.iter() .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(99.0) < 80.0); if low { diff --git a/docs/industries/oil-and-gas/refining.mdx b/docs/industries/oil-and-gas/refining.mdx index 4e6c3d4..9e1848c 100644 --- a/docs/industries/oil-and-gas/refining.mdx +++ b/docs/industries/oil-and-gas/refining.mdx @@ -90,7 +90,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { record_energy_intensity(&p.timestamp, p.sum); } ``` diff --git a/docs/industries/technology-operations/network.mdx b/docs/industries/technology-operations/network.mdx index 521897d..ed8628c 100644 --- a/docs/industries/technology-operations/network.mdx +++ b/docs/industries/technology-operations/network.mdx @@ -100,7 +100,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { flag_if_saturated(&p.timestamp, p.max); } ``` diff --git a/docs/industries/transport-logistics/ports.mdx b/docs/industries/transport-logistics/ports.mdx index 04ba83f..e3b178c 100644 --- a/docs/industries/transport-logistics/ports.mdx +++ b/docs/industries/transport-logistics/ports.mdx @@ -89,7 +89,7 @@ let filter = RetrieveFilter { }; let series = api.time_series .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items().remove(0); + .get_items_mut().remove(0); for p in &series.datapoints { compare_to_target(&p.timestamp, p.sum); } ``` diff --git a/docs/reference/files.md b/docs/reference/files.md index 2170da9..0532fcd 100644 --- a/docs/reference/files.md +++ b/docs/reference/files.md @@ -89,7 +89,7 @@ uploaded = client.files.upload_file(upload) # -> list[INode] use intellistream_datahub_sdk::files::FileUpload; // mime type is inferred from the file content -let mut upload = FileUpload::new_with_destination_path("report.csv", "/reports/2026/"); +let mut upload = FileUpload::new_with_destination_path("report.csv", "/reports/2026/")?; upload.set_external_id("report_2026_q2".into()); upload.set_file_name("q2.csv".into()); upload.set_data_set_id(42); From 756f41235d959028ce2376e90b2e4cb6ff65d254 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 12:58:42 +0200 Subject: [PATCH 07/14] docs(rust): a datapoint's value and time, and the event filter's two types `Datapoint.value` is `Option` and `Datapoint.timestamp` a `DateTime`, so five pages parsed strings that were never strings. `TimeSeries.value_type` is `Option`, which `"numeric".into()` cannot reach on its own. `BasicEventFilter` is gone: the criteria are `EventFilter` and the request body that carries `limit`, `sort` and `cursor` is `EventFilterForm`. `docs/reference/events.md` already described it that way. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/sustained-alarm-window.mdx | 12 +++++------- docs/industries/energy-utilities/waste.mdx | 2 +- .../industries/financial-services/portfolio-risk.mdx | 2 +- docs/industries/manufacturing-process/pharma.mdx | 2 +- .../manufacturing-process/semiconductor.mdx | 2 +- docs/industries/mining-metals/operations.mdx | 2 +- docs/industries/oil-and-gas/production.mdx | 2 +- .../technology-operations/observability.mdx | 12 ++++++------ 8 files changed, 17 insertions(+), 19 deletions(-) diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index 0c2b05e..f22df21 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -323,10 +323,8 @@ let series = api.time_series let mut detector = SustainedHigh::new(SERIES); let (mut raised, mut crossings, mut previous) = (0, 0, 0.0_f64); for p in &series.datapoints { - let millis = p.timestamp.parse::()?; - let at = Utc.timestamp_millis_opt(millis).single().expect("valid time"); - let value = p.value.as_deref() - .and_then(|v| v.parse::().ok()).unwrap_or(0.0); + let at = p.timestamp; + let value = p.value.unwrap_or(0.0); if previous <= LIMIT && value > LIMIT { crossings += 1; } previous = value; if detector.push(&api, at, value).await.is_some() { raised += 1; } @@ -387,10 +385,10 @@ assert len(found) == 1, f"expected one finding, found {len(found)}" ```rust -use intellistream_datahub_sdk::filters::{BasicEventFilter, EventFilter}; +use intellistream_datahub_sdk::filters::{EventFilter, EventFilterForm}; -let filter = EventFilter::default() - .set_filter(BasicEventFilter { +let filter = EventFilterForm::default() + .set_filter(EventFilter { r#type: Some(vec!["sustained_high".into()]), ..Default::default() }) .set_limit(100) .build(); diff --git a/docs/industries/energy-utilities/waste.mdx b/docs/industries/energy-utilities/waste.mdx index 34e624e..3cac011 100644 --- a/docs/industries/energy-utilities/waste.mdx +++ b/docs/industries/energy-utilities/waste.mdx @@ -78,7 +78,7 @@ use intellistream_datahub_sdk::events::Event; let points = api.time_series.retrieve_datapoints(&last_reading("bin_grunerlokka_114_fill_pct")).await? .get_items_mut().remove(0); -let fill: f64 = points.datapoints[0].value.as_deref().unwrap_or("0").parse().unwrap_or(0.0); +let fill: f64 = points.datapoints[0].value.unwrap_or(0.0); if fill >= 80.0 { let mut due = Event::new( format!("collection_due_114_{}", Utc::now().timestamp()), diff --git a/docs/industries/financial-services/portfolio-risk.mdx b/docs/industries/financial-services/portfolio-risk.mdx index ef1557a..48672e4 100644 --- a/docs/industries/financial-services/portfolio-risk.mdx +++ b/docs/industries/financial-services/portfolio-risk.mdx @@ -121,7 +121,7 @@ use chrono::Utc; let mut ts = TimeSeries::new("portfolio_growth_mtm_usd", "Growth portfolio — mark-to-market (USD)"); ts.unit = Some("usd".into()); -ts.value_type = "numeric".into(); +ts.value_type = Some("numeric".into()); ts.data_set_id = desk_id; // desk_id is already Option api.time_series.create_one(&ts).await?; diff --git a/docs/industries/manufacturing-process/pharma.mdx b/docs/industries/manufacturing-process/pharma.mdx index 6ea63f4..89d05d8 100644 --- a/docs/industries/manufacturing-process/pharma.mdx +++ b/docs/industries/manufacturing-process/pharma.mdx @@ -79,7 +79,7 @@ use chrono::Utc; let mut ph = TimeSeries::new("batch_22f_ph", "Batch 22F — pH"); ph.unit = Some("ph".into()); -ph.value_type = "numeric".into(); +ph.value_type = Some("numeric".into()); api.time_series.create_one(&ph).await?; api.time_series diff --git a/docs/industries/manufacturing-process/semiconductor.mdx b/docs/industries/manufacturing-process/semiconductor.mdx index 7c3a14b..e607afe 100644 --- a/docs/industries/manufacturing-process/semiconductor.mdx +++ b/docs/industries/manufacturing-process/semiconductor.mdx @@ -82,7 +82,7 @@ use chrono::Utc; let mut p = TimeSeries::new("tool_etch_07_chamber_pressure_mtorr", "Etch-07 chamber pressure"); p.unit = Some("mtorr".into()); -p.value_type = "numeric".into(); +p.value_type = Some("numeric".into()); api.time_series.create_one(&p).await?; api.time_series diff --git a/docs/industries/mining-metals/operations.mdx b/docs/industries/mining-metals/operations.mdx index 1ba37cc..15173d0 100644 --- a/docs/industries/mining-metals/operations.mdx +++ b/docs/industries/mining-metals/operations.mdx @@ -83,7 +83,7 @@ use chrono::Utc; let points = api.time_series.retrieve_datapoints(&last_hour("truck_785_oil_pressure_kpa")).await? .get_items_mut().remove(0); let low = points.datapoints.iter() - .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(999.0) < 250.0); + .any(|p| p.value.unwrap_or(999.0) < 250.0); if low { let mut warning = Event::new( format!("equipment_warning_785_{}", Utc::now().timestamp()), diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 56457c0..8125f74 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -235,7 +235,7 @@ use intellistream_datahub_sdk::events::Event; let points = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressure_bar")).await? .get_items_mut().remove(0); let low = points.datapoints.iter() - .any(|p| p.value.as_deref().and_then(|v| v.parse::().ok()).unwrap_or(99.0) < 80.0); + .any(|p| p.value.unwrap_or(99.0) < 80.0); if low { let mut event = Event::new( format!("esp_anomaly_a12_{}", Utc::now().timestamp()), diff --git a/docs/industries/technology-operations/observability.mdx b/docs/industries/technology-operations/observability.mdx index ccc2f79..60abb32 100644 --- a/docs/industries/technology-operations/observability.mdx +++ b/docs/industries/technology-operations/observability.mdx @@ -207,13 +207,13 @@ breaches = client.events.filter(intellistream_datahub_sdk.EventFilter( ```rust -use intellistream_datahub_sdk::filters::{BasicEventFilter, EventFilter}; +use intellistream_datahub_sdk::filters::{EventFilter, EventFilterForm}; -let mut basic = BasicEventFilter::default(); -basic.set_type(&["slo_breach"]); -let mut filter = EventFilter::default(); -filter.set_filter(basic); -filter.set_limit(200); +let filter = EventFilterForm::default() + .set_filter(EventFilter { + r#type: Some(vec!["slo_breach".into()]), ..Default::default() }) + .set_limit(200) + .build(); let breaches = api.events.filter(&filter).await?; ``` From d12d20d3b1ea0a03fa2f65d704e6e716564b06c2 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 13:02:41 +0200 Subject: [PATCH 08/14] docs(rust): type the values a reader's own helper returns MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The compile tier cannot infer through a function the page leaves to the reader: every constraint on `inflow` is another such call, so rustc has nowhere to infer from and asks for an annotation. Naming the type is what these pages owed the reader anyway — it is the only statement of what their `latest`, `sum_over`, `tolerance` and `trigger_level` are expected to return. An annotation does not survive being destructured — rustc does not carry it through `if let Some(x)` when the scrutinee came from a name it could not resolve — so the tailings page takes the level as a `&str` and tests it for emptiness instead. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/industries/mining-metals/tailings-safety.mdx | 6 ++++-- docs/industries/oil-and-gas/pipeline.mdx | 4 ++-- docs/industries/oil-and-gas/storage.mdx | 4 ++-- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/docs/industries/mining-metals/tailings-safety.mdx b/docs/industries/mining-metals/tailings-safety.mdx index 2f1cdaa..d19a1e4 100644 --- a/docs/industries/mining-metals/tailings-safety.mdx +++ b/docs/industries/mining-metals/tailings-safety.mdx @@ -94,14 +94,16 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["tsf_instruments"]).await?; while let Some(Ok(msg)) = listener.next().await { - if let Some(level) = trigger_level(&msg.payload) { // "amber" | "red" + // trigger_level is yours: "amber" or "red" when the instrument trips, else None + let level: &str = trigger_level(&msg.payload).unwrap_or(""); + if !level.is_empty() { let mut alarm = Event::new( format!("tailings_alarm_p14_{}", Utc::now().timestamp()), "tailings_alarm".into(), Utc::now()); alarm.status = Some(if level == "red" { "critical" } else { "warning" }.into()); alarm.add_metadata("instrument".into(), "piezometer_p14".into()); - alarm.add_metadata("level".into(), level.into()); + alarm.add_metadata("level".into(), level.to_string()); alarm.add_metadata("pore_pressure_kpa".into(), "186".into()); api.events.create(&vec![alarm]).await?; } diff --git a/docs/industries/oil-and-gas/pipeline.mdx b/docs/industries/oil-and-gas/pipeline.mdx index ff03527..bbb946d 100644 --- a/docs/industries/oil-and-gas/pipeline.mdx +++ b/docs/industries/oil-and-gas/pipeline.mdx @@ -92,8 +92,8 @@ if inflow - outflow > tolerance(inflow): use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let inflow = latest("segment_pn_07_flow_in_m3h").await?; -let outflow = latest("segment_pn_07_flow_out_m3h").await?; +let inflow: f64 = latest("segment_pn_07_flow_in_m3h").await?; +let outflow: f64 = latest("segment_pn_07_flow_out_m3h").await?; if inflow - outflow > tolerance(inflow) { let mut leak = Event::new( diff --git a/docs/industries/oil-and-gas/storage.mdx b/docs/industries/oil-and-gas/storage.mdx index 77541ca..cb80727 100644 --- a/docs/industries/oil-and-gas/storage.mdx +++ b/docs/industries/oil-and-gas/storage.mdx @@ -96,9 +96,9 @@ if abs(unexplained) > tolerance(closing): use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let measured_change = latest("tank_t_12_volume_bbl").await? +let measured_change: f64 = latest("tank_t_12_volume_bbl").await? - first_value("tank_t_12_volume_bbl", shift_start).await?; -let metered = sum_over("tank_t_12_receipts_bbl", shift_start).await? +let metered: f64 = sum_over("tank_t_12_receipts_bbl", shift_start).await? - sum_over("tank_t_12_deliveries_bbl", shift_start).await?; let unexplained = measured_change - metered; From 83ab51479cf3324b4f7de3703e2b83ae084ea31e Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 13:09:59 +0200 Subject: [PATCH 09/14] docs(python): events.filter takes the criteria as keywords The Python client has no `BasicEventFilter`, and `filter()` is keyword-only: either `filter=` with an `EventFilter` or the individual criteria, never both, and paging is always an argument of the call rather than a field of the filter. Seven pages passed a positional `EventFilter` wrapping a `BasicEventFilter`, which is the Rust shape, not this one. `docs/reference/events.md` already described the Python call correctly. This clears the api-surface job: 222 checks, no failures. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/kmeans-clustering.mdx | 3 +-- docs/advanced/pca-process-monitoring.mdx | 3 +-- docs/advanced/sustained-alarm-window.mdx | 3 +-- docs/advanced/xgboost-failure-prediction.mdx | 3 +-- docs/industries/energy-utilities/ev-charging.mdx | 3 +-- docs/industries/oil-and-gas/drilling.mdx | 3 +-- docs/industries/technology-operations/observability.mdx | 3 +-- 7 files changed, 7 insertions(+), 14 deletions(-) diff --git a/docs/advanced/kmeans-clustering.mdx b/docs/advanced/kmeans-clustering.mdx index 7c09c30..de3fb3b 100644 --- a/docs/advanced/kmeans-clustering.mdx +++ b/docs/advanced/kmeans-clustering.mdx @@ -120,8 +120,7 @@ for asset, d in zip(assets, dist): event_time=pd.Timestamp.now(tz="UTC"), metadata={"asset": asset, "cohort": str(int(km.labels_[assets.index(asset)]))})]) -outliers = list(client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="peer_outlier"), limit=100))) +outliers = list(client.events.filter(type="peer_outlier", limit=100)) print(f"{len(outliers)} peer outlier(s) on record") ``` diff --git a/docs/advanced/pca-process-monitoring.mdx b/docs/advanced/pca-process-monitoring.mdx index f2b8224..437e057 100644 --- a/docs/advanced/pca-process-monitoring.mdx +++ b/docs/advanced/pca-process-monitoring.mdx @@ -154,8 +154,7 @@ if t2(znew)[-1] > T2_LIMIT or spe(znew)[-1] > SPE_LIMIT: "top_contributor": culprit})]) # the seeded fault sits in the last ten hours, so the deviation must be on record -found = list(client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="process_deviation"), limit=10))) +found = list(client.events.filter(type="process_deviation", limit=10)) assert found, "the seeded fault should have raised a process_deviation event" print(f"{len(found)} process deviation(s) on record, latest names {found[-1].metadata['top_contributor']}") ``` diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index f22df21..863e5db 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -370,8 +370,7 @@ if (found.getItems().size() != 1) { ```python -found = list(client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="sustained_high"), limit=100))) +found = list(client.events.filter(type="sustained_high", limit=100)) for e in found: print(e.external_id, e.metadata) diff --git a/docs/advanced/xgboost-failure-prediction.mdx b/docs/advanced/xgboost-failure-prediction.mdx index bf10caa..29c3c14 100644 --- a/docs/advanced/xgboost-failure-prediction.mdx +++ b/docs/advanced/xgboost-failure-prediction.mdx @@ -112,8 +112,7 @@ events and label each `(pump, day)` accordingly. # failures: DataFrame of (pump, failed_on), pulled from /events (type = esp_failure) failures = pd.DataFrame([ {"pump": e.metadata.get("pump"), "failed_on": pd.to_datetime(e.event_time, utc=True)} - for e in client.events.filter(intellistream_datahub_sdk.EventFilter( - intellistream_datahub_sdk.BasicEventFilter(type="esp_failure"), limit=1000))]) + for e in client.events.filter(type="esp_failure", limit=1000)]) # one feature row per pump per day across the history you have training_grid = [(p, d) for p in ["pump_esp_a12"] diff --git a/docs/industries/energy-utilities/ev-charging.mdx b/docs/industries/energy-utilities/ev-charging.mdx index dab3e70..858e1ae 100644 --- a/docs/industries/energy-utilities/ev-charging.mdx +++ b/docs/industries/energy-utilities/ev-charging.mdx @@ -115,8 +115,7 @@ close it runs to its grid limit — the input to load-balancing. See The faulted reading in the demo trips the loop, and a `charger_down` event lands: ```python -for e in client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="charger_down"), limit=5)): +for e in client.events.filter(type="charger_down", limit=5): print(e.external_id, e.metadata) # charger_down_oslo_14_… {'charger': 'charger_oslo_14', 'connector': '2'} ``` diff --git a/docs/industries/oil-and-gas/drilling.mdx b/docs/industries/oil-and-gas/drilling.mdx index 6eace09..045f45f 100644 --- a/docs/industries/oil-and-gas/drilling.mdx +++ b/docs/industries/oil-and-gas/drilling.mdx @@ -138,8 +138,7 @@ Run the setup, then the loop above. The demo kick (flow-out climbing past flow-i the detector and a `kick_detected` event lands — confirm it: ```python -hits = client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="kick_detected"), limit=5)) +hits = client.events.filter(type="kick_detected", limit=5) for e in hits: print(e.external_id, "→", e.status) # kick_detected_a12_1751… → critical diff --git a/docs/industries/technology-operations/observability.mdx b/docs/industries/technology-operations/observability.mdx index 60abb32..c8203f7 100644 --- a/docs/industries/technology-operations/observability.mdx +++ b/docs/industries/technology-operations/observability.mdx @@ -199,8 +199,7 @@ DataWrapper breaches = client.events().filter(retriever); ```python -breaches = client.events.filter(intellistream_datahub_sdk.EventFilter( - basic_filter=intellistream_datahub_sdk.BasicEventFilter(type="slo_breach"), limit=200)) +breaches = client.events.filter(type="slo_breach", limit=200) ``` From 755705dcb193a1557320fc72e5ba2e658e678900 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Mon, 28 Sep 2026 13:13:25 +0200 Subject: [PATCH 10/14] test(plans): plans for labels, policies and tenant, and counts that match the pages MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `docs/reference/labels.md`, `policies.md` and `tenant.md` had runnable Java and no plan, so coverage refused them. Each is a reference page whose blocks are separate examples — one of them deleting what an earlier one creates — so each gets `independent = true`, which is also what stops the two "variable already defined" compile errors. Seven plans' block counts had fallen behind their pages. `reference__timeseries` shows why the pin exists: its `exclude = [13]` was written for the signature listing, which is now block 16, so for some time it skipped the latest-datapoint example and compiled the prose. With the selection corrected, the example turns out to name a `DatapointDTO` that does not exist — `latest` answers `DataWrapper>`. `reference__resources` also picks up the blocks #101 and #102 added for the `/functions` endpoints. They are appended, so the plan's `inject before = 8` still lands on "Traverse the graph", which is the block it is there for. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/reference/timeseries.md | 2 +- doctests/plans/guides__ingest-timeseries.toml | 4 ++-- .../plans/reference__binary-datapoints.toml | 1 + doctests/plans/reference__datasets.toml | 2 +- doctests/plans/reference__files.toml | 2 +- doctests/plans/reference__labels.toml | 20 ++++++++++++++++++ doctests/plans/reference__policies.toml | 21 +++++++++++++++++++ doctests/plans/reference__resources.toml | 6 +++--- doctests/plans/reference__tenant.toml | 16 ++++++++++++++ doctests/plans/reference__timeseries.toml | 10 ++++----- 10 files changed, 71 insertions(+), 13 deletions(-) create mode 100644 doctests/plans/reference__labels.toml create mode 100644 doctests/plans/reference__policies.toml create mode 100644 doctests/plans/reference__tenant.toml diff --git a/docs/reference/timeseries.md b/docs/reference/timeseries.md index 798d82b..5c7d741 100644 --- a/docs/reference/timeseries.md +++ b/docs/reference/timeseries.md @@ -799,7 +799,7 @@ It is much cheaper than [retrieve](#retrieve-datapoints) with a limit of one: th is served from the cache the ingest path writes, not from a range scan. ```java -DataWrapper> now = client.timeseries().latest(List.of( +DataWrapper> now = client.timeseries().latest(List.of( IdCollection.createFromExternalId("engine_temperature"), IdCollection.createFromExternalId("engine_pressure"))); ``` diff --git a/doctests/plans/guides__ingest-timeseries.toml b/doctests/plans/guides__ingest-timeseries.toml index d978b89..d227a41 100644 --- a/doctests/plans/guides__ingest-timeseries.toml +++ b/doctests/plans/guides__ingest-timeseries.toml @@ -3,9 +3,9 @@ page = "docs/guides/ingest-timeseries.mdx" # java #1 L46 · python #1 L79 · rust #1 L106 — Ingest a million readings # java #2 L170 · java #3 L208 — Binary ingest (Java) [blocks] -python = 1 +python = 2 java = 3 -rust = 1 +rust = 2 # The page opens on a reader who already has a series. Rather than conjuring one, # the quickstart runs first: this tests that the two pages compose, which is how diff --git a/doctests/plans/reference__binary-datapoints.toml b/doctests/plans/reference__binary-datapoints.toml index c274266..18bddd3 100644 --- a/doctests/plans/reference__binary-datapoints.toml +++ b/doctests/plans/reference__binary-datapoints.toml @@ -5,6 +5,7 @@ page = "docs/reference/binary-datapoints.md" [blocks] python = 1 +rust = 1 [python] # The page's banner: it writes into `engine_temperature`, which section A of the diff --git a/doctests/plans/reference__datasets.toml b/doctests/plans/reference__datasets.toml index fc35bde..d090029 100644 --- a/doctests/plans/reference__datasets.toml +++ b/doctests/plans/reference__datasets.toml @@ -10,7 +10,7 @@ page = "docs/reference/datasets.md" [blocks] python = 3 -java = 3 +java = 4 rust = 3 [python] diff --git a/doctests/plans/reference__files.toml b/doctests/plans/reference__files.toml index 09e9ec4..ce68a7d 100644 --- a/doctests/plans/reference__files.toml +++ b/doctests/plans/reference__files.toml @@ -14,7 +14,7 @@ page = "docs/reference/files.md" [blocks] python = 5 -java = 5 +java = 6 rust = 5 [python] diff --git a/doctests/plans/reference__labels.toml b/doctests/plans/reference__labels.toml new file mode 100644 index 0000000..fe3fe3f --- /dev/null +++ b/doctests/plans/reference__labels.toml @@ -0,0 +1,20 @@ +page = "docs/reference/labels.md" + +# Blocks on this page: +# java #1 L26 Read +# java #2 L37 Create and update +# java #3 L52 Create and update +# java #4 L61 Create and update +# java #5 L70 Delete + +# Pinned so an edit to the page fails this plan instead of silently +# re-pointing its block selections. Update deliberately, after re-reading. +[blocks] +java = 5 + +[java] +disabled = "Java scenario not written yet; compiled by test_compile.py." +# A reference page, not a tutorial: the blocks are separate examples of one call +# each, and #5 deletes the label #2 to #4 create. Compiled one at a time, so +# reusing a name across them is not a redeclaration. +independent = true diff --git a/doctests/plans/reference__policies.toml b/doctests/plans/reference__policies.toml new file mode 100644 index 0000000..45f30ca --- /dev/null +++ b/doctests/plans/reference__policies.toml @@ -0,0 +1,21 @@ +page = "docs/reference/policies.md" + +# Blocks on this page: +# java #1 L25 Policy types {#types} +# java #2 L46 Read, create, update, delete +# java #3 L64 Read, create, update, delete +# java #4 L75 Read, create, update, delete +# java #5 L84 Dry-run a name against the naming policy {#naming-check} +# java #6 L116 Governance templates {#governance-templates} + +# Pinned so an edit to the page fails this plan instead of silently +# re-pointing its block selections. Update deliberately, after re-reading. +[blocks] +java = 6 + +[java] +disabled = "Java scenario not written yet; compiled by test_compile.py." +# A reference page, not a tutorial: each block is a separate example, and the +# create/update/delete trio walks the same policy through its life. Compiled one +# at a time, so the name each reuses is not a redeclaration. +independent = true diff --git a/doctests/plans/reference__resources.toml b/doctests/plans/reference__resources.toml index 7026679..5d50d46 100644 --- a/doctests/plans/reference__resources.toml +++ b/doctests/plans/reference__resources.toml @@ -18,9 +18,9 @@ page = "docs/reference/resources.md" # rust #5 L264 Traverse the graph [blocks] -python = 9 -java = 8 -rust = 8 +python = 10 +java = 11 +rust = 9 [python] timeout = 600 diff --git a/doctests/plans/reference__tenant.toml b/doctests/plans/reference__tenant.toml new file mode 100644 index 0000000..af02469 --- /dev/null +++ b/doctests/plans/reference__tenant.toml @@ -0,0 +1,16 @@ +page = "docs/reference/tenant.md" + +# Blocks on this page: +# java #1 L16 Feature flags {#features} +# java #2 L46 What you may change {#settings-permissions} +# java #3 L61 Model configuration {#llm-settings} + +# Pinned so an edit to the page fails this plan instead of silently +# re-pointing its block selections. Update deliberately, after re-reading. +[blocks] +java = 3 + +[java] +disabled = "Java scenario not written yet; compiled by test_compile.py." +# A reference page, not a tutorial: three unrelated reads of tenant settings. +independent = true diff --git a/doctests/plans/reference__timeseries.toml b/doctests/plans/reference__timeseries.toml index ccc542f..12b8ea6 100644 --- a/doctests/plans/reference__timeseries.toml +++ b/doctests/plans/reference__timeseries.toml @@ -35,9 +35,9 @@ page = "docs/reference/timeseries.md" # java #14 L734 IngestResult [blocks] -python = 9 -java = 14 -rust = 9 +python = 10 +java = 17 +rust = 10 [python] timeout = 600 @@ -58,10 +58,10 @@ client = intellistream_datahub_sdk.DataHubClient.from_env() [java] disabled = "Java scenario not written yet." -# Independent examples, as for Python. #13 is a list of IngestResult's method signatures, +# Independent examples, as for Python. #16 is a list of IngestResult's method signatures, # not code. independent = true -exclude = [13] +exclude = [16] [owns] timeseries = ["book_value_usd", "engine_temperature"] From a002f6551c97f8cd0c01697d7c987a29f8026b5d Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Tue, 29 Sep 2026 14:52:06 +0200 Subject: [PATCH 11/14] test(compile): a page may leave a function to the reader without naming its type MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit rustc reports "type annotations needed" at the *use* of a value destructured out of a call it could not resolve, and no annotation the page could write reaches it: `if let Some(level) = trigger_level(..)` cannot carry one, and the value's only other constraint is another function the page leaves to the reader. There is no Rust counterpart of the Java stubbed pass to settle it either — a stub would need a type of its own, from the same missing information. So E0282 is dropped on any unit that leaves a name to the reader. It can never be how a renamed or removed SDK symbol shows up; that is E0425, E0433, E0412 or E0599, none of which this touches. What it does cost is naming: a page whose own code is genuinely ambiguous stops being caught, if it also leaves a name to the reader. That trade is worth it because the alternative was contorting the prose. The tailings page had grown `unwrap_or("")` and an `is_empty()` test in place of a plain `if let Some(..)`, purely to satisfy this check. It reads as a reader would write it again. The `reader_supplied_destructured` control fails without the change. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- .../mining-metals/tailings-safety.mdx | 6 ++---- doctests/compile_check.py | 17 +++++++++++++++++ doctests/test_compile.py | 8 ++++++++ 3 files changed, 27 insertions(+), 4 deletions(-) diff --git a/docs/industries/mining-metals/tailings-safety.mdx b/docs/industries/mining-metals/tailings-safety.mdx index d19a1e4..2f1cdaa 100644 --- a/docs/industries/mining-metals/tailings-safety.mdx +++ b/docs/industries/mining-metals/tailings-safety.mdx @@ -94,16 +94,14 @@ use chrono::Utc; let mut listener = api.subscriptions.listen(&["tsf_instruments"]).await?; while let Some(Ok(msg)) = listener.next().await { - // trigger_level is yours: "amber" or "red" when the instrument trips, else None - let level: &str = trigger_level(&msg.payload).unwrap_or(""); - if !level.is_empty() { + if let Some(level) = trigger_level(&msg.payload) { // "amber" | "red" let mut alarm = Event::new( format!("tailings_alarm_p14_{}", Utc::now().timestamp()), "tailings_alarm".into(), Utc::now()); alarm.status = Some(if level == "red" { "critical" } else { "warning" }.into()); alarm.add_metadata("instrument".into(), "piezometer_p14".into()); - alarm.add_metadata("level".into(), level.to_string()); + alarm.add_metadata("level".into(), level.into()); alarm.add_metadata("pore_pressure_kpa".into(), "186".into()); api.events.create(&vec![alarm]).await?; } diff --git a/doctests/compile_check.py b/doctests/compile_check.py index 0eee703..125107b 100644 --- a/doctests/compile_check.py +++ b/doctests/compile_check.py @@ -334,6 +334,23 @@ def check_rust(units: list[Unit], workdir: Path, sdk: Path, timeout: int = 1800) rust_placeholder(code, m["message"]))) if proc.returncode != 0 and not reached: raise ToolchainMissing(f"cargo check failed before it reached the docs:\n{proc.stderr[-3000:]}") + + # "Type annotations needed", on a page that leaves something to the reader, is rustc saying it + # lacks information the reader supplies — not a claim about the SDK. There is no Rust + # equivalent of the Java stubbed pass to prove it: a stub would need a type of its own, and + # every constraint on the value is another call the page does not show, so rustc has nowhere to + # infer from either way. It cannot be narrowed by line, because an annotation does not survive + # being destructured: `if let Some(level) = reader_fn(..)` reports E0282 at the *use* of + # `level`, and no annotation the page could write reaches it. + # + # Dropping it costs one thing worth naming: a page whose own code is genuinely ambiguous stops + # being caught, if it also leaves a name to the reader. That is accepted, because the + # alternative was contorting the prose — the tailings page had `unwrap_or("")` and an + # `is_empty()` test in place of a plain `if let Some(..)` purely to satisfy this. A removed or + # renamed SDK symbol is E0425, E0433, E0412 or E0599, none of which this touches. + for name, found in out.items(): + if any(d.placeholder for d in found): + out[name] = [d for d in found if d.placeholder or not d.message.startswith("E0282")] return out diff --git a/doctests/test_compile.py b/doctests/test_compile.py index 5bc5451..b7df21c 100644 --- a/doctests/test_compile.py +++ b/doctests/test_compile.py @@ -86,6 +86,14 @@ def page(self, lang: str) -> docblocks.Page: Control("missing_method_with_reader_argument", "api.time_series.no_such_method_for_doctest(reader_value).await?;", hard_lines=(1,), placeholders=frozenset({"reader_value"})), + # rustc reports E0282 at the *use* of a value destructured out of a reader-supplied call, + # where no annotation the page could write reaches it. The page is what a reader needs; + # only the function is theirs to write. See the note at the end of `check_rust`. + Control("reader_supplied_destructured", + 'if let Some(level) = reader_trigger(&payload) {\n' + ' let owned: String = level.into();\n' + ' println!("{owned}");\n}', + placeholders=frozenset({"reader_trigger", "payload"})), ], } From b4623fef8b30942125ae68bb98a5d5291f025847 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Tue, 29 Sep 2026 14:52:21 +0200 Subject: [PATCH 12/14] docs(units): the lookup by external id is by_external_id in both Python clients The sync client's `by_external_ids` was renamed to `by_external_id` (dataplatform-rust-sdk 96fe3ea), so it no longer differs from the async client, the blocking client or Rust. The page said the two spellings differed; the coverage table said so too. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/industries/energy-utilities/air-quality.mdx | 2 +- docs/reference/units.md | 8 ++++---- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/docs/industries/energy-utilities/air-quality.mdx b/docs/industries/energy-utilities/air-quality.mdx index d5b1b39..546c04b 100644 --- a/docs/industries/energy-utilities/air-quality.mdx +++ b/docs/industries/energy-utilities/air-quality.mdx @@ -55,7 +55,7 @@ client.units().list().getItems().forEach(u -> for u in client.units.list(): print(u.external_id, u.name, u.symbol) -ugm3 = client.units.by_external_ids("ug_m3") # confirm the one you'll use +ugm3 = client.units.by_external_id("ug_m3") # confirm the one you'll use ``` diff --git a/docs/reference/units.md b/docs/reference/units.md index 98a9671..b143b53 100644 --- a/docs/reference/units.md +++ b/docs/reference/units.md @@ -76,12 +76,12 @@ DataWrapper byId = client.units().byIds(List.of(IdCollection.createFr ```python import intellistream_datahub_sdk -by_ext = client.units.by_external_ids("temperature_deg_c") +by_ext = client.units.by_external_id("temperature_deg_c") by_id = client.units.by_ids([intellistream_datahub_sdk.IdCollection(id=7)]) ``` -`by_external_ids` takes one external id and returns a list, empty when no unit has it. The -`AsyncDataHubClient` spells the same call in the singular: +`by_external_id` takes one external id and returns a list, empty when no unit has it. The +`AsyncDataHubClient` awaits the same call: ```python by_ext = await client.units.by_external_id("temperature_deg_c") @@ -109,6 +109,6 @@ An external id no unit has is an error here, not an empty result: `by_external_i | --- | --- | --- | --- | | List all | `units().list` | `units.list` | `units.list` | | Look up by id | `units().byIds` | `units.by_ids` | `units.by_ids` | -| Look up by external id | `units().byIds` | `units.by_external_ids` (sync), `units.by_external_id` (async) | `units.by_external_id` | +| Look up by external id | `units().byIds` | `units.by_external_id` | `units.by_external_id` | The unit catalogue is read-only in every client: units are platform-managed, not tenant data. From dd39973704bd2a20dba91d8ee34d5ac3aa570afa Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Tue, 29 Sep 2026 14:52:21 +0200 Subject: [PATCH 13/14] docs(java): read a DataWrapper by index MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `DataWrapper.getItems()` answers a `List` (datahub-platform#141), so the first of one result is `getItems().get(0)` — which is what these pages said before they were rewritten to `getItems().iterator().next()` to compile against the `Collection` it used to be. All 35 reads go back, including the eight that were written that way from the start, so the site reads one way. `reference/client.md` now says the results are an ordered list, since that is what makes the index meaningful. `timeseries().list(int, long)` takes a numeric data set id and there is no external-id overload, so the example resolves the id through `datasets().byIds` rather than naming a bare `43L`. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/guides/attach-files.mdx | 4 ++-- docs/guides/detect-events.mdx | 2 +- docs/guides/ingest-timeseries.mdx | 2 +- docs/guides/query-and-aggregate.mdx | 2 +- docs/guides/work-with-units.mdx | 6 +++--- docs/industries/financial-services/portfolio-risk.mdx | 2 +- docs/industries/transport-logistics/retail.mdx | 2 +- docs/reference/client.md | 3 ++- docs/reference/edges.md | 2 +- docs/reference/resources.md | 2 +- docs/reference/timeseries.md | 6 +++++- 11 files changed, 19 insertions(+), 14 deletions(-) diff --git a/docs/guides/attach-files.mdx b/docs/guides/attach-files.mdx index 4a683dd..1a7216c 100644 --- a/docs/guides/attach-files.mdx +++ b/docs/guides/attach-files.mdx @@ -37,7 +37,7 @@ var uploaded = client.files().upload( .description("ESP A-12 calibration certificate") .build()); -System.out.println("stored as id " + uploaded.getItems().iterator().next().getId()); +System.out.println("stored as id " + uploaded.getItems().get(0).getId()); ``` @@ -139,7 +139,7 @@ string (the endpoint also accepts an external id in that position). ```java -long id = uploaded.getItems().iterator().next().getId(); +long id = uploaded.getItems().get(0).getId(); byte[] bytes = client.files().download(String.valueOf(id)); Files.write(Path.of("calibration_a12.pdf"), bytes); ``` diff --git a/docs/guides/detect-events.mdx b/docs/guides/detect-events.mdx index d13e1e0..e9d4986 100644 --- a/docs/guides/detect-events.mdx +++ b/docs/guides/detect-events.mdx @@ -36,7 +36,7 @@ filter.setEnd(ZonedDateTime.now()); var request = new DataRetriever(); request.setItems(List.of(filter)); -var series = client.timeseries().retrieve(request).getItems().iterator().next(); +var series = client.timeseries().retrieve(request).getItems().get(0); boolean tooHot = series.getDatapoints().stream() .anyMatch(p -> Double.parseDouble(p.getValue()) > 110.0); diff --git a/docs/guides/ingest-timeseries.mdx b/docs/guides/ingest-timeseries.mdx index 0ff95d9..cc7801c 100644 --- a/docs/guides/ingest-timeseries.mdx +++ b/docs/guides/ingest-timeseries.mdx @@ -210,7 +210,7 @@ firstHour.setLimit(10_000); DataRetriever request = new DataRetriever<>(); request.setItems(List.of(firstHour)); -int n = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints().size(); +int n = client.timeseries().retrieve(request).getItems().get(0).getDatapoints().size(); System.out.printf("%d readings in the first hour%n", n); if (n < 3600) throw new IllegalStateException("expected 3600 readings, got " + n); ``` diff --git a/docs/guides/query-and-aggregate.mdx b/docs/guides/query-and-aggregate.mdx index 9efdab8..a757061 100644 --- a/docs/guides/query-and-aggregate.mdx +++ b/docs/guides/query-and-aggregate.mdx @@ -181,7 +181,7 @@ do { var request = new DataRetriever(); request.setItems(List.of(filter)); - var page = client.timeseries().retrieve(request).getItems().iterator().next(); + var page = client.timeseries().retrieve(request).getItems().get(0); page.getDatapoints().forEach(p -> handle(p)); cursor = page.getNextCursor(); } while (cursor != null); diff --git a/docs/guides/work-with-units.mdx b/docs/guides/work-with-units.mdx index b2b079c..cfc49b9 100644 --- a/docs/guides/work-with-units.mdx +++ b/docs/guides/work-with-units.mdx @@ -103,9 +103,9 @@ Resolve a unit you already know, by external id, or by numeric id. ```java UnitModel celsius = client.units().byIds(List.of( - IdCollection.createFromExternalId("temperature_deg_c"))).getItems().iterator().next(); + IdCollection.createFromExternalId("temperature_deg_c"))).getItems().get(0); UnitModel byId = client.units().byIds(List.of( - IdCollection.createFromId(7))).getItems().iterator().next(); + IdCollection.createFromId(7))).getItems().get(0); ``` @@ -114,7 +114,7 @@ UnitModel byId = client.units().byIds(List.of( ```python import intellistream_datahub_sdk -celsius = client.units.by_external_ids("temperature_deg_c") +celsius = client.units.by_external_id("temperature_deg_c") by_id = client.units.by_ids([intellistream_datahub_sdk.IdCollection(id=7)]) ``` diff --git a/docs/industries/financial-services/portfolio-risk.mdx b/docs/industries/financial-services/portfolio-risk.mdx index 48672e4..21b6706 100644 --- a/docs/industries/financial-services/portfolio-risk.mdx +++ b/docs/industries/financial-services/portfolio-risk.mdx @@ -46,7 +46,7 @@ DataSetModel desk = new DataSetModel(); desk.setExternalId("desk_equities"); desk.setName("Equities desk"); var created = client.datasets().create(List.of(desk)); -long deskId = created.getItems().iterator().next().getId(); +long deskId = created.getItems().get(0).getId(); ``` diff --git a/docs/industries/transport-logistics/retail.mdx b/docs/industries/transport-logistics/retail.mdx index f7bac6b..20ae55b 100644 --- a/docs/industries/transport-logistics/retail.mdx +++ b/docs/industries/transport-logistics/retail.mdx @@ -46,7 +46,7 @@ DataSetModel region = new DataSetModel(); region.setExternalId("region_nordics"); region.setName("Nordics region"); long regionId = client.datasets().create(List.of(region)) - .getItems().iterator().next().getId(); + .getItems().get(0).getId(); var salesSeries = new Timeseries(); salesSeries.setExternalId("store_oslo_01_sku_4471_sales"); diff --git a/docs/reference/client.md b/docs/reference/client.md index 1aff1df..c9fe9dc 100644 --- a/docs/reference/client.md +++ b/docs/reference/client.md @@ -423,7 +423,8 @@ response surfaces as an exception/error carrying the HTTP status, the raw body, -Methods return `DataWrapper`: `getItems()` holds the results. Non-2xx throws +Methods return `DataWrapper`: `getItems()` holds the results, as a `List` in the order the +API returned them, so a single result is `getItems().get(0)`. Non-2xx throws `DatahubApiException`: ```java diff --git a/docs/reference/edges.md b/docs/reference/edges.md index 82eda1b..f9d6c8e 100644 --- a/docs/reference/edges.md +++ b/docs/reference/edges.md @@ -70,7 +70,7 @@ contains.setToExternalId("pump_1"); contains.setRelationshipType("CONTAINS"); DataWrapper created = client.edges().create(List.of(contains)); -System.out.println(created.getItems().iterator().next().getId()); +System.out.println(created.getItems().get(0).getId()); ``` `setName("Flows To")` is the alternative to `setRelationshipType`: it normalises the name to diff --git a/docs/reference/resources.md b/docs/reference/resources.md index f2c1b9a..62794ba 100644 --- a/docs/reference/resources.md +++ b/docs/reference/resources.md @@ -168,7 +168,7 @@ compare the returned items against what you asked for when a miss matters. ```java import ai.intellistream.datahub.models.IdCollection; -NodeModel pump = client.resources().getById(5677892).getItems().iterator().next(); +NodeModel pump = client.resources().getById(5677892).getItems().get(0); DataWrapper some = client.resources().byIds(List.of( IdCollection.createFromExternalId("pump_1"), diff --git a/docs/reference/timeseries.md b/docs/reference/timeseries.md index 5c7d741..8afa883 100644 --- a/docs/reference/timeseries.md +++ b/docs/reference/timeseries.md @@ -375,7 +375,11 @@ because the stored points would no longer parse; create a new series instead. import ai.intellistream.datahub.timeseries.UpdateTimeseries; DataWrapper newest = client.timeseries().list(100); -DataWrapper inSet = client.timeseries().list(100, 43L); // Java takes the numeric dataSetId + +// Java takes the numeric dataSetId, so look the data set up by external id first. +long engineData = client.datasets().byIds(List.of( + IdCollection.createFromExternalId("engine_data"))).getItems().get(0).getId(); +DataWrapper inSet = client.timeseries().list(100, engineData); UpdateTimeseries change = new UpdateTimeseries().setExternalId("engine_temperature"); change.getUpdate().getDescription().set("Engine block temperature, port side"); From 5b31c796069f90e2b6c05dcf1938bf78be2b0d09 Mon Sep 17 00:00:00 2001 From: jgjesdal Date: Tue, 29 Sep 2026 14:52:21 +0200 Subject: [PATCH 14/14] docs(rust): take the first result off a bound response MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit `DataWrapper::get_items` lends the vector, so reading the first of one result in a single expression meant `get_items_mut().remove(0)` — a mutable borrow and a destructive take, in order to read. Binding the response first and indexing it says what the code does, and matches the Python and Java tabs beside it, which both index. Co-Authored-By: Claude Opus 5 (1M context) Signed-off-by: jgjesdal --- docs/advanced/asset-health-score.mdx | 8 ++++---- docs/advanced/demand-forecasting.mdx | 8 ++++---- docs/advanced/kmeans-clustering.mdx | 8 ++++---- docs/advanced/lstm-anomaly-detection.mdx | 8 ++++---- docs/advanced/lstm-forecasting.mdx | 8 ++++---- docs/advanced/pca-process-monitoring.mdx | 8 ++++---- docs/advanced/predictive-maintenance.mdx | 8 ++++---- docs/advanced/random-forest-soft-sensor.mdx | 8 ++++---- docs/advanced/sustained-alarm-window.mdx | 8 ++++---- docs/advanced/xgboost-failure-prediction.mdx | 8 ++++---- .../built-environment/smart-buildings.mdx | 8 ++++---- docs/industries/energy-utilities/grid.mdx | 8 ++++---- docs/industries/energy-utilities/waste.mdx | 6 +++--- docs/industries/energy-utilities/wind.mdx | 8 ++++---- docs/industries/healthcare/patient-flow.mdx | 8 ++++---- docs/industries/manufacturing-process/discrete.mdx | 8 ++++---- docs/industries/mining-metals/operations.mdx | 14 +++++++------- docs/industries/mining-metals/processing-plant.mdx | 8 ++++---- docs/industries/oil-and-gas/emissions.mdx | 8 ++++---- docs/industries/oil-and-gas/production.mdx | 6 +++--- docs/industries/oil-and-gas/refining.mdx | 8 ++++---- docs/industries/technology-operations/network.mdx | 8 ++++---- docs/industries/transport-logistics/ports.mdx | 8 ++++---- 23 files changed, 93 insertions(+), 93 deletions(-) diff --git a/docs/advanced/asset-health-score.mdx b/docs/advanced/asset-health-score.mdx index 7c65003..4cef18a 100644 --- a/docs/advanced/asset-health-score.mdx +++ b/docs/advanced/asset-health-score.mdx @@ -70,7 +70,7 @@ filter.setLimit(100); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); double bearingTemp = Double.parseDouble(pts.get(pts.size() - 1).getValue()); ``` @@ -81,10 +81,10 @@ double bearingTemp = Double.parseDouble(pts.get(pts.size() - 1).getValue()); // The latest datapoint, per signal; the scoring arithmetic below is shown in Python. use intellistream_datahub_sdk::generic::{DataWrapper, IdAndExtId}; -let latest = api.time_series +let page = api.time_series .retrieve_latest_datapoint(&DataWrapper::from(vec![ - IdAndExtId::from_external_id("pump_07_bearing_temp_c")])).await? - .get_items_mut().remove(0); + IdAndExtId::from_external_id("pump_07_bearing_temp_c")])).await?; +let latest = &page.get_items()[0]; let bearing_temp = latest.datapoints.last().and_then(|p| p.value).unwrap_or(f64::NAN); ``` diff --git a/docs/advanced/demand-forecasting.mdx b/docs/advanced/demand-forecasting.mdx index cb01c08..c52d7a2 100644 --- a/docs/advanced/demand-forecasting.mdx +++ b/docs/advanced/demand-forecasting.mdx @@ -68,7 +68,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var history = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var history = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -88,9 +88,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let history = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let history = &page.get_items()[0]; ``` diff --git a/docs/advanced/kmeans-clustering.mdx b/docs/advanced/kmeans-clustering.mdx index de3fb3b..3c3f314 100644 --- a/docs/advanced/kmeans-clustering.mdx +++ b/docs/advanced/kmeans-clustering.mdx @@ -78,7 +78,7 @@ filter.setGranularity("30d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -var sig = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var sig = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -97,9 +97,9 @@ let filter = RetrieveFilter { granularity: Some("30d".into()), ..Default::default() }; -let sig = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let sig = &page.get_items()[0]; ``` diff --git a/docs/advanced/lstm-anomaly-detection.mdx b/docs/advanced/lstm-anomaly-detection.mdx index 20e64c2..3e61858 100644 --- a/docs/advanced/lstm-anomaly-detection.mdx +++ b/docs/advanced/lstm-anomaly-detection.mdx @@ -73,7 +73,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -91,9 +91,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; ``` diff --git a/docs/advanced/lstm-forecasting.mdx b/docs/advanced/lstm-forecasting.mdx index 0f45963..4fd4726 100644 --- a/docs/advanced/lstm-forecasting.mdx +++ b/docs/advanced/lstm-forecasting.mdx @@ -74,7 +74,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -94,9 +94,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; ``` diff --git a/docs/advanced/pca-process-monitoring.mdx b/docs/advanced/pca-process-monitoring.mdx index 437e057..5830b98 100644 --- a/docs/advanced/pca-process-monitoring.mdx +++ b/docs/advanced/pca-process-monitoring.mdx @@ -80,7 +80,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -100,9 +100,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let pts = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let pts = &page.get_items()[0]; ``` diff --git a/docs/advanced/predictive-maintenance.mdx b/docs/advanced/predictive-maintenance.mdx index f34230e..990fbd2 100644 --- a/docs/advanced/predictive-maintenance.mdx +++ b/docs/advanced/predictive-maintenance.mdx @@ -73,7 +73,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var points = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var points = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -91,9 +91,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; ``` diff --git a/docs/advanced/random-forest-soft-sensor.mdx b/docs/advanced/random-forest-soft-sensor.mdx index 61c7445..91f8301 100644 --- a/docs/advanced/random-forest-soft-sensor.mdx +++ b/docs/advanced/random-forest-soft-sensor.mdx @@ -74,7 +74,7 @@ filter.setLimit(100000); var request = new DataRetriever(); request.setItems(List.of(filter)); -var pts = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var pts = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -94,9 +94,9 @@ let filter = RetrieveFilter { limit: Some(100_000), ..Default::default() }; -let pts = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let pts = &page.get_items()[0]; ``` diff --git a/docs/advanced/sustained-alarm-window.mdx b/docs/advanced/sustained-alarm-window.mdx index 863e5db..054d7a1 100644 --- a/docs/advanced/sustained-alarm-window.mdx +++ b/docs/advanced/sustained-alarm-window.mdx @@ -258,7 +258,7 @@ filter.setLimit(10000); DataRetriever request = new DataRetriever<>(); request.setItems(List.of(filter)); var points = client.timeseries().retrieve(request) - .getItems().iterator().next().getDatapoints(); + .getItems().get(0).getDatapoints(); SustainedHigh detector = new SustainedHigh(SERIES); final double LIMIT = SustainedHigh.LIMIT; @@ -316,9 +316,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; let mut detector = SustainedHigh::new(SERIES); let (mut raised, mut crossings, mut previous) = (0, 0, 0.0_f64); diff --git a/docs/advanced/xgboost-failure-prediction.mdx b/docs/advanced/xgboost-failure-prediction.mdx index 29c3c14..aad6e6a 100644 --- a/docs/advanced/xgboost-failure-prediction.mdx +++ b/docs/advanced/xgboost-failure-prediction.mdx @@ -76,7 +76,7 @@ filter.setGranularity("7d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -var agg = client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints(); +var agg = client.timeseries().retrieve(request).getItems().get(0).getDatapoints(); ``` @@ -95,9 +95,9 @@ let filter = RetrieveFilter { granularity: Some("7d".into()), ..Default::default() }; -let agg = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let agg = &page.get_items()[0]; ``` diff --git a/docs/industries/built-environment/smart-buildings.mdx b/docs/industries/built-environment/smart-buildings.mdx index 7a6d26c..79c8750 100644 --- a/docs/industries/built-environment/smart-buildings.mdx +++ b/docs/industries/built-environment/smart-buildings.mdx @@ -128,7 +128,7 @@ filter.setGranularity("1d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> chartDailyKwh(p.getTimestamp(), p.getValue())); ``` @@ -163,9 +163,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { chart_daily_kwh(&p.timestamp, p.sum); } ``` diff --git a/docs/industries/energy-utilities/grid.mdx b/docs/industries/energy-utilities/grid.mdx index ae3cb8d..fa07a9f 100644 --- a/docs/industries/energy-utilities/grid.mdx +++ b/docs/industries/energy-utilities/grid.mdx @@ -122,7 +122,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> chart(p.getTimestamp(), p.getValue())); // hourly load ``` @@ -155,9 +155,9 @@ let filter = RetrieveFilter { granularity: Some("1h".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { chart(&p.timestamp, p.average, p.max); } ``` diff --git a/docs/industries/energy-utilities/waste.mdx b/docs/industries/energy-utilities/waste.mdx index 3cac011..db1af23 100644 --- a/docs/industries/energy-utilities/waste.mdx +++ b/docs/industries/energy-utilities/waste.mdx @@ -41,7 +41,7 @@ Each bin reports its fill level. When a bin crosses its collection threshold, ra ```java var series = client.timeseries().retrieve(lastReadingOf("bin_grunerlokka_114_fill_pct")) - .getItems().iterator().next(); + .getItems().get(0); double fill = Double.parseDouble(series.getDatapoints().get(0).getValue()); if (fill >= 80.0) { @@ -76,8 +76,8 @@ if fill >= 80.0: use chrono::Utc; use intellistream_datahub_sdk::events::Event; -let points = api.time_series.retrieve_datapoints(&last_reading("bin_grunerlokka_114_fill_pct")).await? - .get_items_mut().remove(0); +let page = api.time_series.retrieve_datapoints(&last_reading("bin_grunerlokka_114_fill_pct")).await?; +let points = &page.get_items()[0]; let fill: f64 = points.datapoints[0].value.unwrap_or(0.0); if fill >= 80.0 { let mut due = Event::new( diff --git a/docs/industries/energy-utilities/wind.mdx b/docs/industries/energy-utilities/wind.mdx index 32e8bf1..d00623a 100644 --- a/docs/industries/energy-utilities/wind.mdx +++ b/docs/industries/energy-utilities/wind.mdx @@ -128,7 +128,7 @@ var request = new DataRetriever(); request.setItems(List.of(filter)); double rated = 3500.0; // kW -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> recordCapacityFactor( p.getTimestamp(), Double.parseDouble(p.getValue()) / rated)); ``` @@ -165,9 +165,9 @@ let filter = RetrieveFilter { granularity: Some("1h".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; let rated = 3500.0; for p in &series.datapoints { if let Some(avg) = p.average { record_capacity_factor(&p.timestamp, avg / rated); } diff --git a/docs/industries/healthcare/patient-flow.mdx b/docs/industries/healthcare/patient-flow.mdx index fadaa1c..1be56f9 100644 --- a/docs/industries/healthcare/patient-flow.mdx +++ b/docs/industries/healthcare/patient-flow.mdx @@ -52,7 +52,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> trackStage("time_to_bed", p.getTimestamp(), p.getValue())); ``` @@ -87,9 +87,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { track_stage("time_to_bed", &p.timestamp, p.average); } ``` diff --git a/docs/industries/manufacturing-process/discrete.mdx b/docs/industries/manufacturing-process/discrete.mdx index 0f8860c..0f25708 100644 --- a/docs/industries/manufacturing-process/discrete.mdx +++ b/docs/industries/manufacturing-process/discrete.mdx @@ -117,7 +117,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> recordHourlyPerformance(p.getTimestamp(), p.getValue())); ``` @@ -152,9 +152,9 @@ let filter = RetrieveFilter { granularity: Some("1h".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { record_hourly_performance(&p.timestamp, p.average); } ``` diff --git a/docs/industries/mining-metals/operations.mdx b/docs/industries/mining-metals/operations.mdx index 15173d0..5259f78 100644 --- a/docs/industries/mining-metals/operations.mdx +++ b/docs/industries/mining-metals/operations.mdx @@ -47,7 +47,7 @@ scrambled. See [Turn readings into events](/guides/detect-events). ```java var series = client.timeseries().retrieve(lastHourOf("truck_785_oil_pressure_kpa")) - .getItems().iterator().next(); + .getItems().get(0); if (series.getDatapoints().stream().anyMatch(p -> Double.parseDouble(p.getValue()) < 250.0)) { EventModel warning = new EventModel(); @@ -80,8 +80,8 @@ if any(float(dp.value) < 250.0 for dp in points.get_datapoints()): use intellistream_datahub_sdk::events::Event; use chrono::Utc; -let points = api.time_series.retrieve_datapoints(&last_hour("truck_785_oil_pressure_kpa")).await? - .get_items_mut().remove(0); +let page = api.time_series.retrieve_datapoints(&last_hour("truck_785_oil_pressure_kpa")).await?; +let points = &page.get_items()[0]; let low = points.datapoints.iter() .any(|p| p.value.unwrap_or(999.0) < 250.0); if low { @@ -119,7 +119,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> compareToPlan(p.getTimestamp(), p.getValue())); ``` @@ -154,9 +154,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { compare_to_plan(&p.timestamp, p.average); } ``` diff --git a/docs/industries/mining-metals/processing-plant.mdx b/docs/industries/mining-metals/processing-plant.mdx index c1ac672..3fd2840 100644 --- a/docs/industries/mining-metals/processing-plant.mdx +++ b/docs/industries/mining-metals/processing-plant.mdx @@ -53,7 +53,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> compareToTarget(p.getTimestamp(), p.getValue())); // % recovery ``` @@ -88,9 +88,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { compare_to_target(&p.timestamp, p.average); } ``` diff --git a/docs/industries/oil-and-gas/emissions.mdx b/docs/industries/oil-and-gas/emissions.mdx index f43ab7f..820f5be 100644 --- a/docs/industries/oil-and-gas/emissions.mdx +++ b/docs/industries/oil-and-gas/emissions.mdx @@ -54,7 +54,7 @@ filter.setGranularity("1d"); var request = new DataRetriever(); request.setItems(List.of(filter)); -double monthly = client.timeseries().retrieve(request).getItems().iterator().next() +double monthly = client.timeseries().retrieve(request).getItems().get(0) .getDatapoints().stream().mapToDouble(p -> Double.parseDouble(p.getValue())).sum(); ``` @@ -88,9 +88,9 @@ let filter = RetrieveFilter { granularity: Some("1d".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; let monthly: f64 = series.datapoints.iter() .filter_map(|p| p.sum).sum(); ``` diff --git a/docs/industries/oil-and-gas/production.mdx b/docs/industries/oil-and-gas/production.mdx index 8125f74..228f451 100644 --- a/docs/industries/oil-and-gas/production.mdx +++ b/docs/industries/oil-and-gas/production.mdx @@ -199,7 +199,7 @@ queries open events for the field, and the event references the well it concerns ```java var series = client.timeseries().retrieve(lastHourOf("pump_intake_pressure_bar")) - .getItems().iterator().next(); + .getItems().get(0); if (series.getDatapoints().stream().anyMatch(p -> Double.parseDouble(p.getValue()) < 80.0)) { EventModel event = new EventModel(); @@ -232,8 +232,8 @@ if any(float(dp.value) < 80.0 for dp in points.get_datapoints()): use chrono::Utc; use intellistream_datahub_sdk::events::Event; -let points = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressure_bar")).await? - .get_items_mut().remove(0); +let page = api.time_series.retrieve_datapoints(&last_hour("pump_intake_pressure_bar")).await?; +let points = &page.get_items()[0]; let low = points.datapoints.iter() .any(|p| p.value.unwrap_or(99.0) < 80.0); if low { diff --git a/docs/industries/oil-and-gas/refining.mdx b/docs/industries/oil-and-gas/refining.mdx index 9e1848c..83a6390 100644 --- a/docs/industries/oil-and-gas/refining.mdx +++ b/docs/industries/oil-and-gas/refining.mdx @@ -53,7 +53,7 @@ var request = new DataRetriever(); request.setItems(List.of(filter)); // divide hourly energy by hourly throughput for energy-per-barrel -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> recordEnergyIntensity(p.getTimestamp(), p.getValue())); ``` @@ -88,9 +88,9 @@ let filter = RetrieveFilter { granularity: Some("1h".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { record_energy_intensity(&p.timestamp, p.sum); } ``` diff --git a/docs/industries/technology-operations/network.mdx b/docs/industries/technology-operations/network.mdx index ed8628c..c9d923a 100644 --- a/docs/industries/technology-operations/network.mdx +++ b/docs/industries/technology-operations/network.mdx @@ -63,7 +63,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> flagIfSaturated(p.getTimestamp(), p.getValue())); // PRB utilisation % ``` @@ -98,9 +98,9 @@ let filter = RetrieveFilter { end: Some(Utc::now()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { flag_if_saturated(&p.timestamp, p.max); } ``` diff --git a/docs/industries/transport-logistics/ports.mdx b/docs/industries/transport-logistics/ports.mdx index e3b178c..dcfe99b 100644 --- a/docs/industries/transport-logistics/ports.mdx +++ b/docs/industries/transport-logistics/ports.mdx @@ -52,7 +52,7 @@ filter.setGranularity("1h"); var request = new DataRetriever(); request.setItems(List.of(filter)); -client.timeseries().retrieve(request).getItems().iterator().next().getDatapoints() +client.timeseries().retrieve(request).getItems().get(0).getDatapoints() .forEach(p -> compareToTarget(p.getTimestamp(), p.getValue())); // moves/hour ``` @@ -87,9 +87,9 @@ let filter = RetrieveFilter { granularity: Some("1h".into()), ..Default::default() }; -let series = api.time_series - .retrieve_datapoints(&DataWrapper::from(vec![filter])).await? - .get_items_mut().remove(0); +let page = api.time_series + .retrieve_datapoints(&DataWrapper::from(vec![filter])).await?; +let series = &page.get_items()[0]; for p in &series.datapoints { compare_to_target(&p.timestamp, p.sum); } ```