@golemio/microclimate 1.2.0 → 1.2.1-dev.1133205826

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (55) hide show
  1. package/db/example/99_refresh_materialized_views.sql +3 -0
  2. package/db/migrations/postgresql/20240108122932-improve-sensor-measurements.js +53 -0
  3. package/db/migrations/postgresql/sqls/20240108122932-improve-sensor-measurements-down.sql +77 -0
  4. package/db/migrations/postgresql/sqls/20240108122932-improve-sensor-measurements-up.sql +137 -0
  5. package/dist/index.d.ts +3 -0
  6. package/dist/index.js +31 -0
  7. package/dist/index.js.map +1 -0
  8. package/dist/integration-engine/const.d.ts +2 -0
  9. package/dist/integration-engine/const.js +6 -0
  10. package/dist/integration-engine/const.js.map +1 -0
  11. package/dist/integration-engine/helpers/RawQueryProvider.d.ts +5 -0
  12. package/dist/integration-engine/helpers/RawQueryProvider.js +47 -0
  13. package/dist/integration-engine/helpers/RawQueryProvider.js.map +1 -0
  14. package/dist/integration-engine/ioc/Di.d.ts +3 -0
  15. package/dist/integration-engine/ioc/Di.js +19 -0
  16. package/dist/integration-engine/ioc/Di.js.map +1 -0
  17. package/dist/integration-engine/ioc/ModuleContainerToken.d.ts +5 -0
  18. package/dist/integration-engine/ioc/ModuleContainerToken.js +9 -0
  19. package/dist/integration-engine/ioc/ModuleContainerToken.js.map +1 -0
  20. package/dist/integration-engine/workers/MicroclimateWorker.d.ts +3 -2
  21. package/dist/integration-engine/workers/MicroclimateWorker.js +10 -1
  22. package/dist/integration-engine/workers/MicroclimateWorker.js.map +1 -1
  23. package/dist/integration-engine/workers/tasks/RefreshMeasurementsByIdTask.d.ts +5 -3
  24. package/dist/integration-engine/workers/tasks/RefreshMeasurementsByIdTask.js +27 -8
  25. package/dist/integration-engine/workers/tasks/RefreshMeasurementsByIdTask.js.map +1 -1
  26. package/dist/integration-engine/workers/tasks/RefreshMeasurementsTask.d.ts +2 -0
  27. package/dist/integration-engine/workers/tasks/RefreshMeasurementsTask.js +51 -5
  28. package/dist/integration-engine/workers/tasks/RefreshMeasurementsTask.js.map +1 -1
  29. package/dist/integration-engine/workers/tasks/RefreshSensorViewsTask.d.ts +16 -0
  30. package/dist/integration-engine/workers/tasks/RefreshSensorViewsTask.js +95 -0
  31. package/dist/integration-engine/workers/tasks/RefreshSensorViewsTask.js.map +1 -0
  32. package/dist/output-gateway/MicroclimateRouter.js +12 -12
  33. package/dist/output-gateway/MicroclimateRouter.js.map +1 -1
  34. package/dist/output-gateway/repositories/SensorMeasurementsViewRepository.d.ts +2 -1
  35. package/dist/output-gateway/repositories/SensorMeasurementsViewRepository.js +30 -3
  36. package/dist/output-gateway/repositories/SensorMeasurementsViewRepository.js.map +1 -1
  37. package/dist/schema-definitions/SensorMeasurementsLatestView.d.ts +4 -0
  38. package/dist/schema-definitions/SensorMeasurementsLatestView.js +8 -0
  39. package/dist/schema-definitions/SensorMeasurementsLatestView.js.map +1 -0
  40. package/dist/schema-definitions/SensorMeasurementsView.d.ts +0 -1
  41. package/dist/schema-definitions/SensorMeasurementsView.js.map +1 -1
  42. package/dist/schema-definitions/index.js +6 -4
  43. package/dist/schema-definitions/index.js.map +1 -1
  44. package/dist/schema-definitions/models/SensorMeasurementsLatestViewModel.d.ts +8 -0
  45. package/dist/schema-definitions/models/SensorMeasurementsLatestViewModel.js +13 -0
  46. package/dist/schema-definitions/models/SensorMeasurementsLatestViewModel.js.map +1 -0
  47. package/dist/schema-definitions/models/SensorMeasurementsViewModel.d.ts +0 -1
  48. package/dist/schema-definitions/models/SensorMeasurementsViewModel.js +0 -1
  49. package/dist/schema-definitions/models/SensorMeasurementsViewModel.js.map +1 -1
  50. package/dist/schema-definitions/models/interfaces/ILatestMeasurementDto.d.ts +5 -0
  51. package/dist/schema-definitions/models/interfaces/ILatestMeasurementDto.js +3 -0
  52. package/dist/schema-definitions/models/interfaces/ILatestMeasurementDto.js.map +1 -0
  53. package/docs/assets/microclimate_measure_views_erd.png +0 -0
  54. package/docs/implementation_documentation.md +19 -0
  55. package/package.json +2 -2
@@ -0,0 +1,3 @@
1
+ refresh materialized view v_sensor_points_heights;
2
+ refresh materialized view v_sensor_measurements;
3
+ refresh materialized view v_sensor_measurements_latest;
@@ -0,0 +1,53 @@
1
+ 'use strict';
2
+
3
+ var dbm;
4
+ var type;
5
+ var seed;
6
+ var fs = require('fs');
7
+ var path = require('path');
8
+ var Promise;
9
+
10
+ /**
11
+ * We receive the dbmigrate dependency from dbmigrate initially.
12
+ * This enables us to not have to rely on NODE_PATH.
13
+ */
14
+ exports.setup = function(options, seedLink) {
15
+ dbm = options.dbmigrate;
16
+ type = dbm.dataType;
17
+ seed = seedLink;
18
+ Promise = options.Promise;
19
+ };
20
+
21
+ exports.up = function(db) {
22
+ var filePath = path.join(__dirname, 'sqls', '20240108122932-improve-sensor-measurements-up.sql');
23
+ return new Promise( function( resolve, reject ) {
24
+ fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
25
+ if (err) return reject(err);
26
+ console.log('received data: ' + data);
27
+
28
+ resolve(data);
29
+ });
30
+ })
31
+ .then(function(data) {
32
+ return db.runSql(data);
33
+ });
34
+ };
35
+
36
+ exports.down = function(db) {
37
+ var filePath = path.join(__dirname, 'sqls', '20240108122932-improve-sensor-measurements-down.sql');
38
+ return new Promise( function( resolve, reject ) {
39
+ fs.readFile(filePath, {encoding: 'utf-8'}, function(err,data){
40
+ if (err) return reject(err);
41
+ console.log('received data: ' + data);
42
+
43
+ resolve(data);
44
+ });
45
+ })
46
+ .then(function(data) {
47
+ return db.runSql(data);
48
+ });
49
+ };
50
+
51
+ exports._meta = {
52
+ "version": 1
53
+ };
@@ -0,0 +1,77 @@
1
+ drop materialized view v_sensor_measurements_latest;
2
+ drop materialized view v_sensor_measurements;
3
+ drop materialized view if exists v_sensor_measurements_latest_tmp;
4
+ drop materialized view if exists v_sensor_measurements_tmp;
5
+
6
+ drop function get_sensor_measurements();
7
+ drop materialized view v_sensor_points_heights;
8
+
9
+ CREATE VIEW v_sensor_measurements
10
+ AS
11
+ WITH points_heights AS (
12
+ SELECT s.sensor_id,
13
+ s.point_id,
14
+ s.location_id,
15
+ unpivot.measure,
16
+ unpivot.height_cm,
17
+ CASE
18
+ WHEN unpivot.measure = 'air_temp'::text THEN '°C'::text
19
+ WHEN unpivot.measure = 'air_hum'::text THEN '%'::text
20
+ WHEN unpivot.measure = 'pressure'::text THEN 'Pa'::text
21
+ WHEN unpivot.measure = 'wind_dir'::text THEN '°'::text
22
+ WHEN unpivot.measure = 'wind_impact'::text THEN 'km/h'::text
23
+ WHEN unpivot.measure = 'wind_speed'::text THEN 'km/h'::text
24
+ WHEN unpivot.measure = 'precip'::text THEN 'mm'::text
25
+ WHEN unpivot.measure = 'sun_irr'::text THEN 'lux'::text
26
+ WHEN unpivot.measure = 'soil_temp'::text THEN '°C'::text
27
+ WHEN unpivot.measure = 'water_pot'::text THEN 'kPa'::text
28
+ WHEN unpivot.measure = 'dendro_circ'::text THEN 'mm'::text
29
+ WHEN unpivot.measure = 'dendro_gain'::text THEN 'µm'::text
30
+ ELSE NULL::text
31
+ END AS unit
32
+ FROM sensor_devices_import s,
33
+ LATERAL ( VALUES ('air_temp'::text,s.air_temp), ('air_hum'::text,s.air_hum), ('pressure'::text,s.pressure), ('wind_dir'::text,s.wind_dir), ('wind_impact'::text,s.wind_impact), ('wind_speed'::text,s.wind_speed), ('precip'::text,s.precip), ('sun_irr'::text,s.sun_irr), ('soil_temp'::text,s.soil_temp), ('water_pot'::text,s.water_pot), ('dendro_circ'::text,s.dendro_circ), ('dendro_gain'::text,s.dendro_gain)) unpivot(measure, height_cm)
34
+ WHERE unpivot.height_cm IS NOT NULL
35
+ ), measurements AS (
36
+ SELECT m.sensor_id,
37
+ m.measured_at,
38
+ unpivot.measure,
39
+ unpivot.value
40
+ FROM measurements m
41
+ join sensor_devices_import sdi
42
+ on sdi.sensor_id = m.sensor_id
43
+ and m.measured_at::date >= sdi.data_relevance::date
44
+ and m.measured_at::date <= coalesce(sdi.data_until::date,current_date)
45
+ ,
46
+ LATERAL ( VALUES ('air_temp'::text,m.air_temp), ('air_hum'::text,m.air_hum), ('pressure'::text,m.pressure), ('wind_dir'::text,
47
+ CASE
48
+ WHEN m.wind_dir::text = 'N'::text THEN 0
49
+ WHEN m.wind_dir::text = 'NE'::text THEN 45
50
+ WHEN m.wind_dir::text = 'E'::text THEN 90
51
+ WHEN m.wind_dir::text = 'SE'::text THEN 135
52
+ WHEN m.wind_dir::text = 'S'::text THEN 180
53
+ WHEN m.wind_dir::text = 'SW'::text THEN 225
54
+ WHEN m.wind_dir::text = 'W'::text THEN 270
55
+ WHEN m.wind_dir::text = 'NW'::text THEN 315
56
+ ELSE NULL::integer
57
+ END), ('wind_impact'::text,m.wind_impact), ('wind_speed'::text,m.wind_speed), ('precip'::text,m.precip), ('sun_irr'::text,m.sun_irr), ('soil_temp'::text,m.soil_temp), ('water_pot'::text,m.water_pot), ('dendro_circ'::text,m.dendro_circ), ('dendro_gain'::text,m.dendro_gain)) unpivot(measure, value)
58
+ WHERE unpivot.value IS NOT NULL
59
+ )
60
+ SELECT q.sensor_id,
61
+ q.measured_at,
62
+ q.point_id,
63
+ q.location_id,
64
+ q.measure,
65
+ q.value,
66
+ q.unit,
67
+ row_number() OVER (PARTITION BY q.point_id, q.measure ORDER BY q.point_id, q.measure, q.measured_at DESC) AS rn
68
+ FROM ( SELECT measurements.sensor_id,
69
+ measurements.measured_at,
70
+ points_heights.point_id,
71
+ points_heights.location_id,
72
+ concat(measurements.measure, points_heights.height_cm) AS measure,
73
+ measurements.value,
74
+ points_heights.unit
75
+ FROM measurements
76
+ JOIN points_heights ON points_heights.sensor_id::text = measurements.sensor_id::text AND points_heights.measure = measurements.measure) q
77
+ ORDER BY q.point_id, q.measure, q.measured_at DESC;
@@ -0,0 +1,137 @@
1
+ create materialized view v_sensor_points_heights as
2
+ select s.sensor_id,
3
+ s.point_id,
4
+ s.location_id,
5
+ s.data_relevance,
6
+ s.data_until,
7
+ unpivot.measure,
8
+ unpivot.height_cm,
9
+ CASE
10
+ WHEN unpivot.measure = 'air_temp'::text THEN '°C'::text
11
+ WHEN unpivot.measure = 'air_hum'::text THEN '%'::text
12
+ WHEN unpivot.measure = 'pressure'::text THEN 'Pa'::text
13
+ WHEN unpivot.measure = 'wind_dir'::text THEN '°'::text
14
+ WHEN unpivot.measure = 'wind_impact'::text THEN 'km/h'::text
15
+ WHEN unpivot.measure = 'wind_speed'::text THEN 'km/h'::text
16
+ WHEN unpivot.measure = 'precip'::text THEN 'mm'::text
17
+ WHEN unpivot.measure = 'sun_irr'::text THEN 'lux'::text
18
+ WHEN unpivot.measure = 'soil_temp'::text THEN '°C'::text
19
+ WHEN unpivot.measure = 'water_pot'::text THEN 'kPa'::text
20
+ WHEN unpivot.measure = 'dendro_circ'::text THEN 'mm'::text
21
+ WHEN unpivot.measure = 'dendro_gain'::text THEN 'µm'::text
22
+ ELSE NULL::text
23
+ END AS unit
24
+ from
25
+ sensor_devices_import s,
26
+ LATERAL ( VALUES ('air_temp'::text,s.air_temp), ('air_hum'::text,s.air_hum), ('pressure'::text,s.pressure), ('wind_dir'::text,s.wind_dir), ('wind_impact'::text,s.wind_impact), ('wind_speed'::text,s.wind_speed), ('precip'::text,s.precip), ('sun_irr'::text,s.sun_irr), ('soil_temp'::text,s.soil_temp), ('water_pot'::text,s.water_pot), ('dendro_circ'::text,s.dendro_circ), ('dendro_gain'::text,s.dendro_gain)) unpivot(measure, height_cm)
27
+ where unpivot.height_cm IS NOT NULL;
28
+
29
+ create index v_sensor_points_heights_idx ON v_sensor_points_heights (sensor_id, measure, data_relevance, data_until);
30
+
31
+
32
+ create function get_sensor_measurements()
33
+ returns table(
34
+ sensor_id varchar(50),
35
+ measured_at timestamptz,
36
+ point_id int,
37
+ location_id int,
38
+ measure text,
39
+ "value" float8,
40
+ unit text
41
+ )
42
+ language sql
43
+ set search_path from current
44
+ AS $function$
45
+ with Measures as (
46
+ select unnest(array[
47
+ 'air_temp', 'air_hum', 'pressure',
48
+ 'wind_dir', 'wind_impact', 'wind_speed',
49
+ 'precip', 'sun_irr', 'soil_temp',
50
+ 'water_pot', 'dendro_circ', 'dendro_gain'
51
+ ]) AS measure
52
+ ), MeasurementsData as (
53
+ select m.sensor_id,
54
+ sdi.point_id,
55
+ sdi.location_id,
56
+ sdi.unit,
57
+ m.measured_at,
58
+ Measures.measure || height_cm as measure,
59
+ CASE
60
+ WHEN Measures.measure = 'wind_dir' THEN (
61
+ CASE
62
+ WHEN m.wind_dir::text = 'N'::text THEN 0
63
+ WHEN m.wind_dir::text = 'NE'::text THEN 45
64
+ WHEN m.wind_dir::text = 'E'::text THEN 90
65
+ WHEN m.wind_dir::text = 'SE'::text THEN 135
66
+ WHEN m.wind_dir::text = 'S'::text THEN 180
67
+ WHEN m.wind_dir::text = 'SW'::text THEN 225
68
+ WHEN m.wind_dir::text = 'W'::text THEN 270
69
+ WHEN m.wind_dir::text = 'NW'::text THEN 315
70
+ ELSE NULL::integer
71
+ END
72
+ )
73
+ when Measures.measure = 'air_temp' then m.air_temp
74
+ when Measures.measure = 'air_hum' then m.air_hum
75
+ when Measures.measure = 'pressure' then m.pressure
76
+ when Measures.measure = 'wind_impact' then m.wind_impact
77
+ when Measures.measure = 'wind_speed' then m.wind_speed
78
+ when Measures.measure = 'precip' then m.precip
79
+ when Measures.measure = 'sun_irr' then m.sun_irr
80
+ when Measures.measure = 'soil_temp' then m.soil_temp
81
+ when Measures.measure = 'water_pot' then m.water_pot
82
+ when Measures.measure = 'dendro_circ' then m.dendro_circ
83
+ when Measures.measure = 'dendro_gain' then m.dendro_gain
84
+ ELSE sdi.height_cm
85
+ END AS value
86
+ from
87
+ measurements m
88
+ cross join Measures
89
+ join v_sensor_points_heights sdi
90
+ ON sdi.sensor_id = m.sensor_id and sdi.measure = Measures.measure
91
+ where m.measured_at::date >= sdi.data_relevance AND m.measured_at::date <= coalesce(sdi.data_until, current_date)
92
+ )
93
+ select
94
+ sensor_id,
95
+ measured_at,
96
+ point_id,
97
+ location_id,
98
+ measure,
99
+ "value",
100
+ unit
101
+ from
102
+ MeasurementsData
103
+ where "value" is not null
104
+ $function$;
105
+
106
+
107
+ create materialized view v_sensor_measurements_tmp as
108
+ select * from get_sensor_measurements()
109
+ with no data;
110
+
111
+
112
+ -- create indexes
113
+ create index on v_sensor_measurements_tmp (point_id, measure, measured_at desc);
114
+ create index on v_sensor_measurements_tmp (location_id);
115
+
116
+
117
+ -- populate the materialized view
118
+ refresh materialized view v_sensor_measurements_tmp;
119
+
120
+ create materialized view v_sensor_measurements_latest_tmp as
121
+ select
122
+ point_id,
123
+ measure,
124
+ max(measured_at) as measured_at
125
+ from
126
+ v_sensor_measurements_tmp
127
+ group by
128
+ point_id,
129
+ measure;
130
+
131
+ create unique index on v_sensor_measurements_latest_tmp (point_id, measure);
132
+
133
+ -- replace current view with the new materialized view
134
+ alter view v_sensor_measurements rename to v_sensor_measurements_old;
135
+ alter materialized view v_sensor_measurements_tmp rename to v_sensor_measurements;
136
+ alter materialized view v_sensor_measurements_latest_tmp rename to v_sensor_measurements_latest;
137
+ drop view v_sensor_measurements_old;
@@ -0,0 +1,3 @@
1
+ export * as IntegrationEngine from "./integration-engine";
2
+ export * as OutputGateway from "./output-gateway";
3
+ export * as SchemaDefinitions from "./schema-definitions";
package/dist/index.js ADDED
@@ -0,0 +1,31 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
14
+ Object.defineProperty(o, "default", { enumerable: true, value: v });
15
+ }) : function(o, v) {
16
+ o["default"] = v;
17
+ });
18
+ var __importStar = (this && this.__importStar) || function (mod) {
19
+ if (mod && mod.__esModule) return mod;
20
+ var result = {};
21
+ if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k);
22
+ __setModuleDefault(result, mod);
23
+ return result;
24
+ };
25
+ Object.defineProperty(exports, "__esModule", { value: true });
26
+ exports.SchemaDefinitions = exports.OutputGateway = exports.IntegrationEngine = void 0;
27
+ // Library exports
28
+ exports.IntegrationEngine = __importStar(require("./integration-engine"));
29
+ exports.OutputGateway = __importStar(require("./output-gateway"));
30
+ exports.SchemaDefinitions = __importStar(require("./schema-definitions"));
31
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;AAAA,kBAAkB;AAClB,0EAAyC;AACzC,kEAAqC;AACrC,0EAA0C"}
@@ -0,0 +1,2 @@
1
+ export declare const MICROCLIMATE_WORKER_NAME = "Microclimate";
2
+ export declare const ORIGIN_HOSTNAME_HEADER = "x-origin-hostname";
@@ -0,0 +1,6 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ORIGIN_HOSTNAME_HEADER = exports.MICROCLIMATE_WORKER_NAME = void 0;
4
+ exports.MICROCLIMATE_WORKER_NAME = "Microclimate";
5
+ exports.ORIGIN_HOSTNAME_HEADER = "x-origin-hostname";
6
+ //# sourceMappingURL=const.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"const.js","sourceRoot":"","sources":["../../src/integration-engine/const.ts"],"names":[],"mappings":";;;AAAa,QAAA,wBAAwB,GAAG,cAAc,CAAC;AAC1C,QAAA,sBAAsB,GAAG,mBAAmB,CAAC"}
@@ -0,0 +1,5 @@
1
+ export declare class RawQueryProvider {
2
+ static getRefreshPointsHeightsQuery(): string;
3
+ static getRefreshSensorMeasurementsQuery(): string;
4
+ static getSwapSensorMeasurementsQuery(): string;
5
+ }
@@ -0,0 +1,47 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.RawQueryProvider = void 0;
4
+ const _sch_1 = require("../../schema-definitions");
5
+ class RawQueryProvider {
6
+ static getRefreshPointsHeightsQuery() {
7
+ // only very short lock time is expected (around 600 ms at most)
8
+ // hence no need to use concurrent refresh
9
+ return `refresh materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_points_heights;`;
10
+ }
11
+ static getRefreshSensorMeasurementsQuery() {
12
+ return `
13
+ drop materialized view if exists ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_latest_tmp;
14
+ drop materialized view if exists ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp;
15
+
16
+ create materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp as
17
+ select * from ${_sch_1.Microclimate.pgSchema}.get_sensor_measurements()
18
+ with no data;
19
+ create index on ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp (point_id, measure, measured_at desc);
20
+ create index on ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp (location_id);
21
+ refresh materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp;
22
+
23
+ create materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_latest_tmp as
24
+ select
25
+ point_id,
26
+ measure,
27
+ max(measured_at) as measured_at
28
+ from
29
+ ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp
30
+ group by
31
+ point_id,
32
+ measure;
33
+
34
+ create unique index on ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_latest_tmp (point_id, measure);`;
35
+ }
36
+ static getSwapSensorMeasurementsQuery() {
37
+ return `
38
+ drop materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_latest;
39
+ drop materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements;
40
+ alter materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_tmp
41
+ rename to v_sensor_measurements;
42
+ alter materialized view ${_sch_1.Microclimate.pgSchema}.v_sensor_measurements_latest_tmp
43
+ rename to v_sensor_measurements_latest;`;
44
+ }
45
+ }
46
+ exports.RawQueryProvider = RawQueryProvider;
47
+ //# sourceMappingURL=RawQueryProvider.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RawQueryProvider.js","sourceRoot":"","sources":["../../../src/integration-engine/helpers/RawQueryProvider.ts"],"names":[],"mappings":";;;AAAA,mDAAoC;AAEpC,MAAa,gBAAgB;IAClB,MAAM,CAAC,4BAA4B;QACtC,gEAAgE;QAChE,0CAA0C;QAC1C,OAAO,6BAA6B,mBAAY,CAAC,QAAQ,2BAA2B,CAAC;IACzF,CAAC;IAEM,MAAM,CAAC,iCAAiC;QAC3C,OAAO;+CACgC,mBAAY,CAAC,QAAQ;+CACrB,mBAAY,CAAC,QAAQ;;uCAE7B,mBAAY,CAAC,QAAQ;gCAC5B,mBAAY,CAAC,QAAQ;;8BAEvB,mBAAY,CAAC,QAAQ;8BACrB,mBAAY,CAAC,QAAQ;wCACX,mBAAY,CAAC,QAAQ;;uCAEtB,mBAAY,CAAC,QAAQ;;;;;;kBAM1C,mBAAY,CAAC,QAAQ;;;;;qCAKF,mBAAY,CAAC,QAAQ,wDAAwD,CAAC;IAC/G,CAAC;IAEM,MAAM,CAAC,8BAA8B;QACxC,OAAO;qCACsB,mBAAY,CAAC,QAAQ;qCACrB,mBAAY,CAAC,QAAQ;sCACpB,mBAAY,CAAC,QAAQ;;sCAErB,mBAAY,CAAC,QAAQ;wDACH,CAAC;IACrD,CAAC;CACJ;AA1CD,4CA0CC"}
@@ -0,0 +1,3 @@
1
+ import { DependencyContainer } from "@golemio/core/dist/shared/tsyringe";
2
+ declare const MicroclimateContainer: DependencyContainer;
3
+ export { MicroclimateContainer };
@@ -0,0 +1,19 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.MicroclimateContainer = void 0;
4
+ const const_1 = require("../const");
5
+ const RefreshSensorViewsTask_1 = require("../workers/tasks/RefreshSensorViewsTask");
6
+ const pubsub_1 = require("@golemio/core/dist/integration-engine/data-access/pubsub");
7
+ const Di_1 = require("@golemio/core/dist/integration-engine/ioc/Di");
8
+ const ModuleContainerToken_1 = require("./ModuleContainerToken");
9
+ //#region Initialization
10
+ // Explicit annotation is needed here for local development with linked core module
11
+ const MicroclimateContainer = Di_1.IntegrationEngineContainer.createChildContainer();
12
+ exports.MicroclimateContainer = MicroclimateContainer;
13
+ //#endregion
14
+ //#region Helpers
15
+ MicroclimateContainer.registerInstance(ModuleContainerToken_1.ModuleContainerToken.RedisPubSubChannel, new pubsub_1.RedisPubSubChannel(const_1.MICROCLIMATE_WORKER_NAME));
16
+ //#endregion
17
+ //#region Tasks
18
+ MicroclimateContainer.registerSingleton(ModuleContainerToken_1.ModuleContainerToken.RefreshSensorViewsTask, RefreshSensorViewsTask_1.RefreshSensorViewsTask);
19
+ //# sourceMappingURL=Di.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Di.js","sourceRoot":"","sources":["../../../src/integration-engine/ioc/Di.ts"],"names":[],"mappings":";;;AAAA,oCAAqD;AACrD,oFAAkF;AAClF,qFAA8F;AAC9F,qEAA0F;AAC1F,iEAA8D;AAG9D,wBAAwB;AACxB,mFAAmF;AACnF,MAAM,qBAAqB,GAAwB,+BAA0B,CAAC,oBAAoB,EAAE,CAAC;AAW5F,sDAAqB;AAV9B,YAAY;AAEZ,iBAAiB;AACjB,qBAAqB,CAAC,gBAAgB,CAAC,2CAAoB,CAAC,kBAAkB,EAAE,IAAI,2BAAkB,CAAC,gCAAwB,CAAC,CAAC,CAAC;AAClI,YAAY;AAEZ,eAAe;AACf,qBAAqB,CAAC,iBAAiB,CAAC,2CAAoB,CAAC,sBAAsB,EAAE,+CAAsB,CAAC,CAAC"}
@@ -0,0 +1,5 @@
1
+ declare const ModuleContainerToken: {
2
+ RedisPubSubChannel: symbol;
3
+ RefreshSensorViewsTask: symbol;
4
+ };
5
+ export { ModuleContainerToken };
@@ -0,0 +1,9 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.ModuleContainerToken = void 0;
4
+ const ModuleContainerToken = {
5
+ RedisPubSubChannel: Symbol(),
6
+ RefreshSensorViewsTask: Symbol(),
7
+ };
8
+ exports.ModuleContainerToken = ModuleContainerToken;
9
+ //# sourceMappingURL=ModuleContainerToken.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ModuleContainerToken.js","sourceRoot":"","sources":["../../../src/integration-engine/ioc/ModuleContainerToken.ts"],"names":[],"mappings":";;;AAAA,MAAM,oBAAoB,GAAG;IACzB,kBAAkB,EAAE,MAAM,EAAE;IAC5B,sBAAsB,EAAE,MAAM,EAAE;CACnC,CAAC;AAEO,oDAAoB"}
@@ -1,5 +1,6 @@
1
- import { AbstractWorker } from "@golemio/core/dist/integration-engine/workers";
1
+ import { AbstractTask, AbstractWorker } from "@golemio/core/dist/integration-engine/workers";
2
2
  export declare class MicroclimateWorker extends AbstractWorker {
3
- protected readonly name = "Microclimate";
3
+ protected name: string;
4
4
  constructor();
5
+ registerTask: (task: AbstractTask<any>) => void;
5
6
  }
@@ -1,12 +1,21 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.MicroclimateWorker = void 0;
4
+ const const_1 = require("../const");
5
+ const Di_1 = require("../ioc/Di");
6
+ const ModuleContainerToken_1 = require("../ioc/ModuleContainerToken");
4
7
  const workers_1 = require("@golemio/core/dist/integration-engine/workers");
5
8
  const tasks_1 = require("./tasks");
6
9
  class MicroclimateWorker extends workers_1.AbstractWorker {
7
10
  constructor() {
8
11
  super();
9
- this.name = "Microclimate";
12
+ this.name = const_1.MICROCLIMATE_WORKER_NAME;
13
+ this.registerTask = (task) => {
14
+ super.registerTask(task);
15
+ task.queuePrefix = this.getQueuePrefix();
16
+ };
17
+ // Register tasks
18
+ this.registerTask(Di_1.MicroclimateContainer.resolve(ModuleContainerToken_1.ModuleContainerToken.RefreshSensorViewsTask));
10
19
  this.registerTask(new tasks_1.RefreshSensorDevicesTask(this.getQueuePrefix()));
11
20
  this.registerTask(new tasks_1.RefreshMeasurementsTask(this.getQueuePrefix()));
12
21
  this.registerTask(new tasks_1.RefreshMeasurementsByIdTask(this.getQueuePrefix()));
@@ -1 +1 @@
1
- {"version":3,"file":"MicroclimateWorker.js","sourceRoot":"","sources":["../../../src/integration-engine/workers/MicroclimateWorker.ts"],"names":[],"mappings":";;;AAAA,2EAA+E;AAC/E,mCAAyG;AAEzG,MAAa,kBAAmB,SAAQ,wBAAc;IAGlD;QACI,KAAK,EAAE,CAAC;QAHO,SAAI,GAAG,cAAc,CAAC;QAIrC,IAAI,CAAC,YAAY,CAAC,IAAI,gCAAwB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY,CAAC,IAAI,+BAAuB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,YAAY,CAAC,IAAI,mCAA2B,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;CACJ;AATD,gDASC"}
1
+ {"version":3,"file":"MicroclimateWorker.js","sourceRoot":"","sources":["../../../src/integration-engine/workers/MicroclimateWorker.ts"],"names":[],"mappings":";;;AAAA,oCAAqD;AACrD,kCAAmD;AACnD,sEAAoE;AACpE,2EAA6F;AAC7F,mCAAyG;AAEzG,MAAa,kBAAmB,SAAQ,wBAAc;IAGlD;QACI,KAAK,EAAE,CAAC;QAHF,SAAI,GAAG,gCAAwB,CAAC;QAYnC,iBAAY,GAAG,CAAC,IAAuB,EAAQ,EAAE;YACpD,KAAK,CAAC,YAAY,CAAC,IAAI,CAAC,CAAC;YACzB,IAAI,CAAC,WAAW,GAAG,IAAI,CAAC,cAAc,EAAE,CAAC;QAC7C,CAAC,CAAC;QAVE,iBAAiB;QACjB,IAAI,CAAC,YAAY,CAAC,0BAAqB,CAAC,OAAO,CAAC,2CAAoB,CAAC,sBAAsB,CAAC,CAAC,CAAC;QAC9F,IAAI,CAAC,YAAY,CAAC,IAAI,gCAAwB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACvE,IAAI,CAAC,YAAY,CAAC,IAAI,+BAAuB,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;QACtE,IAAI,CAAC,YAAY,CAAC,IAAI,mCAA2B,CAAC,IAAI,CAAC,cAAc,EAAE,CAAC,CAAC,CAAC;IAC9E,CAAC;CAMJ;AAjBD,gDAiBC"}
@@ -1,11 +1,13 @@
1
- import { AbstractTask } from "@golemio/core/dist/integration-engine";
2
- import { IRefreshMeasurementsByIdTask } from "../../../schema-definitions/Measurements";
3
1
  import { RefreshMeasurementsByIdTaskSchema } from "../../schema/RefreshMeasurementsByIdTaskSchema";
2
+ import { IRefreshMeasurementsByIdTask } from "../../../schema-definitions/Measurements";
3
+ import { AbstractTask } from "@golemio/core/dist/integration-engine";
4
+ import { MessageProperties } from "amqplib";
4
5
  export declare class RefreshMeasurementsByIdTask extends AbstractTask<IRefreshMeasurementsByIdTask> {
5
6
  readonly queueName = "refreshMeasurementsById";
6
7
  readonly schema: typeof RefreshMeasurementsByIdTaskSchema;
7
8
  private transformation;
8
9
  private repository;
10
+ private microclimateRedisChannel;
9
11
  constructor(queuePrefix: string);
10
- protected execute(msg: IRefreshMeasurementsByIdTask): Promise<void>;
12
+ protected execute(msg: IRefreshMeasurementsByIdTask, msgProperties?: MessageProperties): Promise<void>;
11
13
  }
@@ -10,11 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.RefreshMeasurementsByIdTask = void 0;
13
- const integration_engine_1 = require("@golemio/core/dist/integration-engine");
14
- const RefreshMeasurementsByIdTaskSchema_1 = require("../../schema/RefreshMeasurementsByIdTaskSchema");
13
+ const const_1 = require("../../const");
15
14
  const MeasurementsDataSourceFactory_1 = require("../../datasources/MeasurementsDataSourceFactory");
16
- const MeasurementsTransformation_1 = require("../../transformations/MeasurementsTransformation");
15
+ const Di_1 = require("../../ioc/Di");
16
+ const ModuleContainerToken_1 = require("../../ioc/ModuleContainerToken");
17
17
  const repositories_1 = require("../../repositories");
18
+ const RefreshMeasurementsByIdTaskSchema_1 = require("../../schema/RefreshMeasurementsByIdTaskSchema");
19
+ const MeasurementsTransformation_1 = require("../../transformations/MeasurementsTransformation");
20
+ const integration_engine_1 = require("@golemio/core/dist/integration-engine");
21
+ const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
18
22
  class RefreshMeasurementsByIdTask extends integration_engine_1.AbstractTask {
19
23
  constructor(queuePrefix) {
20
24
  super(queuePrefix);
@@ -22,13 +26,28 @@ class RefreshMeasurementsByIdTask extends integration_engine_1.AbstractTask {
22
26
  this.schema = RefreshMeasurementsByIdTaskSchema_1.RefreshMeasurementsByIdTaskSchema;
23
27
  this.transformation = new MeasurementsTransformation_1.MeasurementsTransformation();
24
28
  this.repository = new repositories_1.MeasurementsRepository();
29
+ this.microclimateRedisChannel = Di_1.MicroclimateContainer.resolve(ModuleContainerToken_1.ModuleContainerToken.RedisPubSubChannel);
25
30
  }
26
- execute(msg) {
31
+ execute(msg, msgProperties) {
27
32
  return __awaiter(this, void 0, void 0, function* () {
28
- const dataSource = MeasurementsDataSourceFactory_1.MeasurementsDataSourceFactory.getDataSource(msg);
29
- const data = yield dataSource.getAll();
30
- const transformedData = yield this.transformation.transform(data, msg.sensorAddr);
31
- yield this.repository.saveBulk(transformedData);
33
+ let errorMessage = null;
34
+ try {
35
+ const dataSource = MeasurementsDataSourceFactory_1.MeasurementsDataSourceFactory.getDataSource(msg);
36
+ const data = yield dataSource.getAll();
37
+ const transformedData = yield this.transformation.transform(data, msg.sensorAddr);
38
+ yield this.repository.saveBulk(transformedData);
39
+ }
40
+ catch (err) {
41
+ errorMessage = err.message;
42
+ }
43
+ if (msgProperties === null || msgProperties === void 0 ? void 0 : msgProperties.headers[const_1.ORIGIN_HOSTNAME_HEADER]) {
44
+ yield this.microclimateRedisChannel.publishMessage(`${errorMessage !== null && errorMessage !== void 0 ? errorMessage : "OK"}`, {
45
+ channelSuffix: msgProperties.headers[const_1.ORIGIN_HOSTNAME_HEADER],
46
+ });
47
+ }
48
+ if (errorMessage) {
49
+ throw new golemio_errors_1.GeneralError(errorMessage, this.constructor.name);
50
+ }
32
51
  });
33
52
  }
34
53
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RefreshMeasurementsByIdTask.js","sourceRoot":"","sources":["../../../../src/integration-engine/workers/tasks/RefreshMeasurementsByIdTask.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8EAAqE;AAErE,sGAAiG;AACjG,mGAA8F;AAC9F,iGAA4F;AAC5F,qDAA0D;AAE1D,MAAa,2BAA4B,SAAQ,iCAA0C;IAMvF,YAAY,WAAmB;QAC3B,KAAK,CAAC,WAAW,CAAC,CAAC;QANP,cAAS,GAAG,yBAAyB,CAAC;QACtC,WAAM,GAAG,qEAAiC,CAAC;QAMvD,IAAI,CAAC,cAAc,GAAG,IAAI,uDAA0B,EAAE,CAAC;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,qCAAsB,EAAE,CAAC;IACnD,CAAC;IAEe,OAAO,CAAC,GAAiC;;YACrD,MAAM,UAAU,GAAG,6DAA6B,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;YACpE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;YACvC,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;YAClF,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;QACpD,CAAC;KAAA;CACJ;AAlBD,kEAkBC"}
1
+ {"version":3,"file":"RefreshMeasurementsByIdTask.js","sourceRoot":"","sources":["../../../../src/integration-engine/workers/tasks/RefreshMeasurementsByIdTask.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,uCAAmD;AACnD,mGAA8F;AAC9F,qCAAmD;AACnD,yEAAoE;AACpE,qDAA0D;AAC1D,sGAAiG;AACjG,iGAA4F;AAE5F,8EAAqE;AAErE,6EAAwE;AAGxE,MAAa,2BAA4B,SAAQ,iCAA0C;IAQvF,YAAY,WAAmB;QAC3B,KAAK,CAAC,WAAW,CAAC,CAAC;QARP,cAAS,GAAG,yBAAyB,CAAC;QACtC,WAAM,GAAG,qEAAiC,CAAC;QAQvD,IAAI,CAAC,cAAc,GAAG,IAAI,uDAA0B,EAAE,CAAC;QACvD,IAAI,CAAC,UAAU,GAAG,IAAI,qCAAsB,EAAE,CAAC;QAC/C,IAAI,CAAC,wBAAwB,GAAG,0BAAqB,CAAC,OAAO,CACzD,2CAAoB,CAAC,kBAAkB,CAC1C,CAAC;IACN,CAAC;IAEe,OAAO,CAAC,GAAiC,EAAE,aAAiC;;YACxF,IAAI,YAAY,GAAkB,IAAI,CAAC;YAEvC,IAAI;gBACA,MAAM,UAAU,GAAG,6DAA6B,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;gBACpE,MAAM,IAAI,GAAG,MAAM,UAAU,CAAC,MAAM,EAAE,CAAC;gBACvC,MAAM,eAAe,GAAG,MAAM,IAAI,CAAC,cAAc,CAAC,SAAS,CAAC,IAAI,EAAE,GAAG,CAAC,UAAU,CAAC,CAAC;gBAClF,MAAM,IAAI,CAAC,UAAU,CAAC,QAAQ,CAAC,eAAe,CAAC,CAAC;aACnD;YAAC,OAAO,GAAG,EAAE;gBACV,YAAY,GAAG,GAAG,CAAC,OAAO,CAAC;aAC9B;YAED,IAAI,aAAa,aAAb,aAAa,uBAAb,aAAa,CAAE,OAAO,CAAC,8BAAsB,CAAC,EAAE;gBAChD,MAAM,IAAI,CAAC,wBAAwB,CAAC,cAAc,CAAC,GAAG,YAAY,aAAZ,YAAY,cAAZ,YAAY,GAAI,IAAI,EAAE,EAAE;oBAC1E,aAAa,EAAE,aAAa,CAAC,OAAO,CAAC,8BAAsB,CAAC;iBAC/D,CAAC,CAAC;aACN;YAED,IAAI,YAAY,EAAE;gBACd,MAAM,IAAI,6BAAY,CAAC,YAAY,EAAE,IAAI,CAAC,WAAW,CAAC,IAAI,CAAC,CAAC;aAC/D;QACL,CAAC;KAAA;CACJ;AAvCD,kEAuCC"}
@@ -5,7 +5,9 @@ export interface ISensorIdObject {
5
5
  export declare class RefreshMeasurementsTask extends AbstractEmptyTask {
6
6
  readonly queueName = "refreshMeasurements";
7
7
  readonly queueTtl: number;
8
+ private logger;
8
9
  private repository;
10
+ private microclimateRedisChannel;
9
11
  constructor(queuePrefix: string);
10
12
  protected execute(): Promise<void>;
11
13
  }
@@ -8,17 +8,28 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
8
8
  step((generator = generator.apply(thisArg, _arguments || [])).next());
9
9
  });
10
10
  };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
11
14
  Object.defineProperty(exports, "__esModule", { value: true });
12
15
  exports.RefreshMeasurementsTask = void 0;
13
- const integration_engine_1 = require("@golemio/core/dist/integration-engine");
16
+ const const_1 = require("../../const");
17
+ const Di_1 = require("../../ioc/Di");
18
+ const ModuleContainerToken_1 = require("../../ioc/ModuleContainerToken");
14
19
  const repositories_1 = require("../../repositories");
15
20
  const Measurements_1 = require("../../../schema-definitions/Measurements");
21
+ const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
22
+ const integration_engine_1 = require("@golemio/core/dist/integration-engine");
23
+ const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
24
+ const node_os_1 = __importDefault(require("node:os"));
16
25
  class RefreshMeasurementsTask extends integration_engine_1.AbstractEmptyTask {
17
26
  constructor(queuePrefix) {
18
27
  super(queuePrefix);
19
28
  this.queueName = "refreshMeasurements";
20
29
  this.queueTtl = 23 * 60 * 60 * 1000; // 23 hours
21
30
  this.repository = new repositories_1.SensorDevicesRepository();
31
+ this.logger = Di_1.MicroclimateContainer.resolve(CoreToken_1.CoreToken.Logger);
32
+ this.microclimateRedisChannel = Di_1.MicroclimateContainer.resolve(ModuleContainerToken_1.ModuleContainerToken.RedisPubSubChannel);
22
33
  }
23
34
  execute() {
24
35
  return __awaiter(this, void 0, void 0, function* () {
@@ -26,14 +37,49 @@ class RefreshMeasurementsTask extends integration_engine_1.AbstractEmptyTask {
26
37
  attributes: ["sensor_id"],
27
38
  raw: true,
28
39
  });
29
- const promises = sensorDevicesFromDB.map((sensorIdObject) => {
40
+ if (sensorDevicesFromDB.length === 0) {
41
+ this.logger.warn("SensorMeasurements: no sensor devices found");
42
+ return;
43
+ }
44
+ const subscriber = this.microclimateRedisChannel.createSubscriber({
45
+ channelSuffix: node_os_1.default.hostname(),
46
+ maxMessageCount: sensorDevicesFromDB.length,
47
+ });
48
+ yield subscriber.subscribe();
49
+ for (const sensorIdObject of sensorDevicesFromDB) {
30
50
  const msg = {
31
51
  sensorAddr: sensorIdObject.sensor_id,
32
52
  dateRange: Measurements_1.DateRange.TODAY,
33
53
  };
34
- return integration_engine_1.QueueManager.sendMessageToExchange(this.queuePrefix, "refreshMeasurementsById", msg);
35
- });
36
- yield Promise.all(promises);
54
+ integration_engine_1.QueueManager.sendMessageToExchange(this.queuePrefix, "refreshMeasurementsById", msg, {
55
+ headers: {
56
+ [const_1.ORIGIN_HOSTNAME_HEADER]: node_os_1.default.hostname(),
57
+ },
58
+ });
59
+ }
60
+ // Listen for messages from workers and wait for all of them to finish
61
+ // before continuing to the next step (refresh sensor views)
62
+ try {
63
+ yield subscriber.listen(({ message, messageCount, isFinal }) => {
64
+ this.logger.info(`SensorMeasurements: received message: ${message} (${messageCount}/${sensorDevicesFromDB.length})`);
65
+ if (!message.startsWith("OK")) {
66
+ this.logger.error(`SensorMeasurements: subscription error: ${message}`);
67
+ }
68
+ if (isFinal) {
69
+ this.logger.info("SensorMeasurements: all messages received");
70
+ }
71
+ });
72
+ }
73
+ catch (err) {
74
+ if (err instanceof golemio_errors_1.AbstractGolemioError) {
75
+ throw err;
76
+ }
77
+ throw new golemio_errors_1.GeneralError("Error while listening for messages", this.constructor.name, err);
78
+ }
79
+ finally {
80
+ yield subscriber.unsubscribe();
81
+ integration_engine_1.QueueManager.sendMessageToExchange(this.queuePrefix, "refreshSensorViews", {});
82
+ }
37
83
  });
38
84
  }
39
85
  }
@@ -1 +1 @@
1
- {"version":3,"file":"RefreshMeasurementsTask.js","sourceRoot":"","sources":["../../../../src/integration-engine/workers/tasks/RefreshMeasurementsTask.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8EAAwF;AACxF,qDAA2D;AAC3D,2EAA4E;AAM5E,MAAa,uBAAwB,SAAQ,sCAAiB;IAM1D,YAAY,WAAmB;QAC3B,KAAK,CAAC,WAAW,CAAC,CAAC;QANP,cAAS,GAAG,qBAAqB,CAAC;QAClC,aAAQ,GAAG,EAAE,GAAG,EAAE,GAAG,EAAE,GAAG,IAAI,CAAC,CAAC,WAAW;QAMvD,IAAI,CAAC,UAAU,GAAG,IAAI,sCAAuB,EAAE,CAAC;IACpD,CAAC;IAEe,OAAO;;YACnB,MAAM,mBAAmB,GAAsB,MAAM,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC;gBACtE,UAAU,EAAE,CAAC,WAAW,CAAC;gBACzB,GAAG,EAAE,IAAI;aACZ,CAAC,CAAC;YAEH,MAAM,QAAQ,GAAG,mBAAmB,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE;gBACxD,MAAM,GAAG,GAAiC;oBACtC,UAAU,EAAE,cAAc,CAAC,SAAS;oBACpC,SAAS,EAAE,wBAAS,CAAC,KAAK;iBAC7B,CAAC;gBAEF,OAAO,iCAAY,CAAC,qBAAqB,CAAC,IAAI,CAAC,WAAW,EAAE,yBAAyB,EAAE,GAAG,CAAC,CAAC;YAChG,CAAC,CAAC,CAAC;YACH,MAAM,OAAO,CAAC,GAAG,CAAC,QAAQ,CAAC,CAAC;QAChC,CAAC;KAAA;CACJ;AA3BD,0DA2BC"}
1
+ {"version":3,"file":"RefreshMeasurementsTask.js","sourceRoot":"","sources":["../../../../src/integration-engine/workers/tasks/RefreshMeasurementsTask.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,16 @@
1
+ import { ISimpleConfig } from "@golemio/core/dist/helpers/configuration/ISimpleConfig";
2
+ import { IDatabaseConnector } from "@golemio/core/dist/helpers/data-access/postgres/IDatabaseConnector";
3
+ import { IoRedisConnector } from "@golemio/core/dist/helpers/data-access/redis/IoRedisConnector";
4
+ import { ILogger } from "@golemio/core/dist/helpers/logger";
5
+ import { AbstractEmptyTask } from "@golemio/core/dist/integration-engine/workers";
6
+ export declare class RefreshSensorViewsTask extends AbstractEmptyTask {
7
+ private logger;
8
+ private redisClient;
9
+ private postgresClient;
10
+ readonly queueName = "refreshSensorViews";
11
+ readonly queueTtl: number;
12
+ private lockTimeout;
13
+ constructor(config: ISimpleConfig, logger: ILogger, redisClient: IoRedisConnector, postgresClient: IDatabaseConnector);
14
+ protected execute(): Promise<void>;
15
+ private createMutex;
16
+ }
@@ -0,0 +1,95 @@
1
+ "use strict";
2
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
3
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
4
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
5
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
6
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
7
+ };
8
+ var __metadata = (this && this.__metadata) || function (k, v) {
9
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
10
+ };
11
+ var __param = (this && this.__param) || function (paramIndex, decorator) {
12
+ return function (target, key) { decorator(target, key, paramIndex); }
13
+ };
14
+ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
15
+ function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
16
+ return new (P || (P = Promise))(function (resolve, reject) {
17
+ function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
18
+ function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
19
+ function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
20
+ step((generator = generator.apply(thisArg, _arguments || [])).next());
21
+ });
22
+ };
23
+ Object.defineProperty(exports, "__esModule", { value: true });
24
+ exports.RefreshSensorViewsTask = void 0;
25
+ const const_1 = require("../../const");
26
+ const RawQueryProvider_1 = require("../../helpers/RawQueryProvider");
27
+ const IoRedisConnector_1 = require("@golemio/core/dist/helpers/data-access/redis/IoRedisConnector");
28
+ const CoreToken_1 = require("@golemio/core/dist/helpers/ioc/CoreToken");
29
+ const ioc_1 = require("@golemio/core/dist/integration-engine/ioc");
30
+ const workers_1 = require("@golemio/core/dist/integration-engine/workers");
31
+ const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
32
+ const redis_semaphore_1 = require("@golemio/core/dist/shared/redis-semaphore");
33
+ const tsyringe_1 = require("@golemio/core/dist/shared/tsyringe");
34
+ let RefreshSensorViewsTask = exports.RefreshSensorViewsTask = class RefreshSensorViewsTask extends workers_1.AbstractEmptyTask {
35
+ constructor(config, logger, redisClient, postgresClient) {
36
+ super(const_1.MICROCLIMATE_WORKER_NAME);
37
+ this.logger = logger;
38
+ this.redisClient = redisClient;
39
+ this.postgresClient = postgresClient;
40
+ this.queueName = "refreshSensorViews";
41
+ this.queueTtl = 10 * 60 * 1000; // 10 minutes
42
+ this.lockTimeout = config.getValue("old.datasources.microclimate.sensorMeasurements.mutexLockTimeout", 9 * 60 * 1000); // default 9 minutes
43
+ }
44
+ execute() {
45
+ return __awaiter(this, void 0, void 0, function* () {
46
+ const mutex = this.createMutex();
47
+ let lockAcquired = false;
48
+ try {
49
+ lockAcquired = yield mutex.tryAcquire();
50
+ }
51
+ catch (err) {
52
+ throw new golemio_errors_1.GeneralError(`${this.constructor.name}: error while acquiring mutex lock`, this.constructor.name, err);
53
+ }
54
+ if (!lockAcquired) {
55
+ this.logger.info(`${this.constructor.name}: mutex lock was not acquired`);
56
+ return;
57
+ }
58
+ const connection = this.postgresClient.getConnection();
59
+ try {
60
+ // refresh points heights (from imported sensor devices)
61
+ yield connection.query(RawQueryProvider_1.RawQueryProvider.getRefreshPointsHeightsQuery());
62
+ // refresh sensor measurements views
63
+ yield connection.query(RawQueryProvider_1.RawQueryProvider.getRefreshSensorMeasurementsQuery());
64
+ // swap views
65
+ yield connection.query(RawQueryProvider_1.RawQueryProvider.getSwapSensorMeasurementsQuery());
66
+ }
67
+ catch (err) {
68
+ throw new golemio_errors_1.GeneralError(`${this.constructor.name}: error while refreshing sensor views`, this.constructor.name, err);
69
+ }
70
+ finally {
71
+ yield mutex.release().catch((err) => {
72
+ this.logger.error(`${this.constructor.name}: error while releasing mutex: ${err.message}`);
73
+ });
74
+ }
75
+ });
76
+ }
77
+ createMutex() {
78
+ return new redis_semaphore_1.Mutex(this.redisClient.getConnection(), this.queuePrefix, {
79
+ acquireAttemptsLimit: 1,
80
+ lockTimeout: this.lockTimeout,
81
+ onLockLost: (err) => {
82
+ this.logger.error(err, `${this.constructor.name}: mutex lock was lost`);
83
+ },
84
+ });
85
+ }
86
+ };
87
+ exports.RefreshSensorViewsTask = RefreshSensorViewsTask = __decorate([
88
+ (0, tsyringe_1.injectable)(),
89
+ __param(0, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.SimpleConfig)),
90
+ __param(1, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.Logger)),
91
+ __param(2, (0, tsyringe_1.inject)(ioc_1.ContainerToken.RedisConnector)),
92
+ __param(3, (0, tsyringe_1.inject)(CoreToken_1.CoreToken.PostgresConnector)),
93
+ __metadata("design:paramtypes", [Object, Object, IoRedisConnector_1.IoRedisConnector, Object])
94
+ ], RefreshSensorViewsTask);
95
+ //# sourceMappingURL=RefreshSensorViewsTask.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"RefreshSensorViewsTask.js","sourceRoot":"","sources":["../../../../src/integration-engine/workers/tasks/RefreshSensorViewsTask.ts"],"names":[],"mappings":"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"}
@@ -10,15 +10,15 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.microclimateRouter = void 0;
13
- const express_1 = require("@golemio/core/dist/shared/express");
14
- const express_validator_1 = require("@golemio/core/dist/shared/express-validator");
15
- const BaseRouter_1 = require("@golemio/core/dist/output-gateway/routes/BaseRouter");
16
- const output_gateway_1 = require("@golemio/core/dist/output-gateway");
17
- const repositories_1 = require("./repositories");
18
13
  const LocationsOutputMapper_1 = require("./helpers/LocationsOutputMapper");
19
- const SensorPointsViewRepository_1 = require("./repositories/SensorPointsViewRepository");
20
- const SensorMeasurementsViewRepository_1 = require("./repositories/SensorMeasurementsViewRepository");
21
14
  const PointsOutputMapper_1 = require("./helpers/PointsOutputMapper");
15
+ const repositories_1 = require("./repositories");
16
+ const SensorMeasurementsViewRepository_1 = require("./repositories/SensorMeasurementsViewRepository");
17
+ const SensorPointsViewRepository_1 = require("./repositories/SensorPointsViewRepository");
18
+ const output_gateway_1 = require("@golemio/core/dist/output-gateway");
19
+ const BaseRouter_1 = require("@golemio/core/dist/output-gateway/routes/BaseRouter");
20
+ const express_1 = require("@golemio/core/dist/shared/express");
21
+ const express_validator_1 = require("@golemio/core/dist/shared/express-validator");
22
22
  class MicroclimateRouter extends BaseRouter_1.BaseRouter {
23
23
  constructor() {
24
24
  super();
@@ -63,21 +63,21 @@ class MicroclimateRouter extends BaseRouter_1.BaseRouter {
63
63
  next(err);
64
64
  }
65
65
  });
66
- this.initRoutes = () => {
67
- this.router.get("/locations", [(0, express_validator_1.query)("locationId'").optional().isInt()], output_gateway_1.checkErrors, (0, output_gateway_1.useCacheMiddleware)(), this.getLocations);
68
- this.router.get("/points", [(0, express_validator_1.query)("locationId'").optional().isInt(), (0, express_validator_1.query)("pointId").optional().isInt()], output_gateway_1.checkErrors, (0, output_gateway_1.useCacheMiddleware)(), this.getPoints);
66
+ this.initRoutes = (ttlString) => {
67
+ this.router.get("/locations", [(0, express_validator_1.query)("locationId'").optional().isInt()], output_gateway_1.checkErrors, (0, output_gateway_1.useCacheMiddleware)(ttlString), this.getLocations);
68
+ this.router.get("/points", [(0, express_validator_1.query)("locationId'").optional().isInt(), (0, express_validator_1.query)("pointId").optional().isInt()], output_gateway_1.checkErrors, (0, output_gateway_1.useCacheMiddleware)(ttlString), this.getPoints);
69
69
  this.router.get("/measurements", [
70
70
  (0, express_validator_1.query)("locationId'").optional().isInt(),
71
71
  (0, express_validator_1.query)("pointId").optional().isInt(),
72
72
  (0, express_validator_1.query)("measure").optional().isString(),
73
73
  (0, express_validator_1.query)("from").optional().isISO8601(),
74
74
  (0, express_validator_1.query)("to").optional().isISO8601(),
75
- ], output_gateway_1.pagination, output_gateway_1.checkErrors, (0, output_gateway_1.useCacheMiddleware)(), this.getMeasurements);
75
+ ], output_gateway_1.pagination, output_gateway_1.checkErrors, (0, output_gateway_1.paginationLimitMiddleware)("MicroclimateRouter"), (0, output_gateway_1.useCacheMiddleware)(ttlString), this.getMeasurements);
76
76
  };
77
77
  this.sensorDevicesImportRepository = new repositories_1.SensorDevicesImportRepository();
78
78
  this.sensorPointsViewRepository = new SensorPointsViewRepository_1.SensorPointsViewRepository();
79
79
  this.sensorMeasurementsViewRepository = new SensorMeasurementsViewRepository_1.SensorMeasurementsViewRepository();
80
- this.initRoutes();
80
+ this.initRoutes("10 seconds");
81
81
  }
82
82
  }
83
83
  const microclimateRouter = new MicroclimateRouter().router;
@@ -1 +1 @@
1
- {"version":3,"file":"MicroclimateRouter.js","sourceRoot":"","sources":["../../src/output-gateway/MicroclimateRouter.ts"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"MicroclimateRouter.js","sourceRoot":"","sources":["../../src/output-gateway/MicroclimateRouter.ts"],"names":[],"mappings":"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"}
@@ -1,6 +1,7 @@
1
- import { SequelizeModel } from "@golemio/core/dist/output-gateway";
2
1
  import { ISensorMeasurementsView } from "../../schema-definitions/SensorMeasurementsView";
2
+ import { SequelizeModel } from "@golemio/core/dist/output-gateway";
3
3
  export declare class SensorMeasurementsViewRepository extends SequelizeModel {
4
+ private measurementsLatestViewModel;
4
5
  constructor();
5
6
  GetAllMeasurements: (options?: {
6
7
  locationId?: number;
@@ -10,14 +10,16 @@ var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, ge
10
10
  };
11
11
  Object.defineProperty(exports, "__esModule", { value: true });
12
12
  exports.SensorMeasurementsViewRepository = void 0;
13
- const output_gateway_1 = require("@golemio/core/dist/output-gateway");
14
13
  const _sch_1 = require("../../schema-definitions");
14
+ const SensorMeasurementsLatestViewModel_1 = require("../../schema-definitions/models/SensorMeasurementsLatestViewModel");
15
15
  const SensorMeasurementsViewModel_1 = require("../../schema-definitions/models/SensorMeasurementsViewModel");
16
+ const output_gateway_1 = require("@golemio/core/dist/output-gateway");
16
17
  const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
17
18
  class SensorMeasurementsViewRepository extends output_gateway_1.SequelizeModel {
18
19
  constructor() {
19
20
  super(_sch_1.Microclimate.definitions.sensorMeasurementsView.name, _sch_1.Microclimate.definitions.sensorMeasurementsView.pgTableName, SensorMeasurementsViewModel_1.SensorMeasurementsViewModel.attributeModel, {
20
21
  schema: _sch_1.Microclimate.pgSchema,
22
+ timestamps: false,
21
23
  });
22
24
  this.GetAllMeasurements = (options = {}) => __awaiter(this, void 0, void 0, function* () {
23
25
  var _a;
@@ -28,19 +30,44 @@ class SensorMeasurementsViewRepository extends output_gateway_1.SequelizeModel {
28
30
  ...(options.measure ? [{ measure: { [sequelize_1.Op.eq]: options.measure } }] : []),
29
31
  ...(options.from ? [{ measured_at: { [sequelize_1.Op.gte]: options.from } }] : []),
30
32
  ...(options.to ? [{ measured_at: { [sequelize_1.Op.lte]: options.to } }] : []),
31
- ...(!options.from && !options.to ? [{ rn: { [sequelize_1.Op.eq]: 1 } }] : []),
32
33
  ],
33
34
  };
35
+ const joinAttributes = Object.assign({ [sequelize_1.Op.and]: [sequelize_1.Sequelize.literal("latest.measure = v_sensor_measurements.measure")] }, (!options.from && !options.to
36
+ ? [sequelize_1.Sequelize.literal("latest.measured_at = v_sensor_measurements.measured_at")]
37
+ : []));
34
38
  return this.sequelizeModel.findAll({
35
39
  attributes: {
36
- exclude: ["sensor_id", "rn"],
40
+ exclude: ["sensor_id"],
37
41
  },
42
+ include: [
43
+ {
44
+ model: this.measurementsLatestViewModel,
45
+ as: "latest",
46
+ attributes: [],
47
+ where: joinAttributes,
48
+ },
49
+ ],
38
50
  where: whereAttributes,
39
51
  limit: options.limit,
40
52
  offset: (_a = options.offset) !== null && _a !== void 0 ? _a : 0,
53
+ order: [
54
+ ["point_id", "asc"],
55
+ ["measure", "asc"],
56
+ ["measured_at", "desc"],
57
+ ],
41
58
  });
42
59
  });
43
60
  this.sequelizeModel.removeAttribute("id");
61
+ // Associations
62
+ this.measurementsLatestViewModel = this.sequelizeModel["sequelize"].define(_sch_1.Microclimate.definitions.sensorMeasurementsLatestView.pgTableName, SensorMeasurementsLatestViewModel_1.SensorMeasurementsLatestViewModel.attributeModel, {
63
+ schema: _sch_1.Microclimate.pgSchema,
64
+ timestamps: false,
65
+ });
66
+ this.sequelizeModel.hasOne(this.measurementsLatestViewModel, {
67
+ foreignKey: "point_id",
68
+ sourceKey: "point_id",
69
+ as: "latest",
70
+ });
44
71
  }
45
72
  GetAll() {
46
73
  throw new Error("Not implemented");
@@ -1 +1 @@
1
- {"version":3,"file":"SensorMeasurementsViewRepository.js","sourceRoot":"","sources":["../../../src/output-gateway/repositories/SensorMeasurementsViewRepository.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,sEAAmE;AACnE,mDAAoC;AACpC,6GAAsF;AAEtF,mEAAuE;AAEvE,MAAa,gCAAiC,SAAQ,+BAAc;IAChE;QACI,KAAK,CACD,mBAAY,CAAC,WAAW,CAAC,sBAAsB,CAAC,IAAI,EACpD,mBAAY,CAAC,WAAW,CAAC,sBAAsB,CAAC,WAAW,EAC3D,yDAA2B,CAAC,cAAc,EAC1C;YACI,MAAM,EAAE,mBAAY,CAAC,QAAQ;SAChC,CACJ,CAAC;QAIC,uBAAkB,GAAG,CACxB,UAQI,EAAE,EAC4B,EAAE;;YACpC,MAAM,eAAe,GAAiB;gBAClC,CAAC,cAAE,CAAC,GAAG,CAAC,EAAE;oBACN,GAAG,CAAC,OAAO,CAAC,UAAU,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,cAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,UAAU,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACjF,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,QAAQ,EAAE,EAAE,CAAC,cAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACxE,GAAG,CAAC,OAAO,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC,EAAE,OAAO,EAAE,EAAE,CAAC,cAAE,CAAC,EAAE,CAAC,EAAE,OAAO,CAAC,OAAO,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACvE,GAAG,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,cAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBACtE,GAAG,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,WAAW,EAAE,EAAE,CAAC,cAAE,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC,EAAE,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;oBAClE,GAAG,CAAC,CAAC,OAAO,CAAC,IAAI,IAAI,CAAC,OAAO,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,EAAE,EAAE,EAAE,CAAC,cAAE,CAAC,EAAE,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,EAAE,CAAC;iBACpE;aACJ,CAAC;YACF,OAAO,IAAI,CAAC,cAAc,CAAC,OAAO,CAAC;gBAC/B,UAAU,EAAE;oBACR,OAAO,EAAE,CAAC,WAAW,EAAE,IAAI,CAAC;iBAC/B;gBACD,KAAK,EAAE,eAAe;gBACtB,KAAK,EAAE,OAAO,CAAC,KAAK;gBACpB,MAAM,EAAE,MAAA,OAAO,CAAC,MAAM,mCAAI,CAAC;aAC9B,CAAC,CAAC;QACP,CAAC,CAAA,CAAC;QAhCE,IAAI,CAAC,cAAc,CAAC,eAAe,CAAC,IAAI,CAAC,CAAC;IAC9C,CAAC;IAiCD,MAAM;QACF,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvC,CAAC;IAED,MAAM;QACF,MAAM,IAAI,KAAK,CAAC,iBAAiB,CAAC,CAAC;IACvC,CAAC;CACJ;AAnDD,4EAmDC"}
1
+ {"version":3,"file":"SensorMeasurementsViewRepository.js","sourceRoot":"","sources":["../../../src/output-gateway/repositories/SensorMeasurementsViewRepository.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,4 @@
1
+ export declare const sensorMeasurementsLatestView: {
2
+ name: string;
3
+ pgTableName: string;
4
+ };
@@ -0,0 +1,8 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.sensorMeasurementsLatestView = void 0;
4
+ exports.sensorMeasurementsLatestView = {
5
+ name: "SensorMeasurementsLatestView",
6
+ pgTableName: "v_sensor_measurements_latest",
7
+ };
8
+ //# sourceMappingURL=SensorMeasurementsLatestView.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SensorMeasurementsLatestView.js","sourceRoot":"","sources":["../../src/schema-definitions/SensorMeasurementsLatestView.ts"],"names":[],"mappings":";;;AAAa,QAAA,4BAA4B,GAAG;IACxC,IAAI,EAAE,8BAA8B;IACpC,WAAW,EAAE,8BAA8B;CAC9C,CAAC"}
@@ -6,7 +6,6 @@ export interface ISensorMeasurementsView {
6
6
  measure: string;
7
7
  value: number;
8
8
  unit: string;
9
- rn?: number;
10
9
  }
11
10
  export declare const sensorMeasurementsView: {
12
11
  name: string;
@@ -1 +1 @@
1
- {"version":3,"file":"SensorMeasurementsView.js","sourceRoot":"","sources":["../../src/schema-definitions/SensorMeasurementsView.ts"],"names":[],"mappings":";;;AAWa,QAAA,sBAAsB,GAAG;IAClC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,uBAAuB;CACvC,CAAC"}
1
+ {"version":3,"file":"SensorMeasurementsView.js","sourceRoot":"","sources":["../../src/schema-definitions/SensorMeasurementsView.ts"],"names":[],"mappings":";;;AAUa,QAAA,sBAAsB,GAAG;IAClC,IAAI,EAAE,wBAAwB;IAC9B,WAAW,EAAE,uBAAuB;CACvC,CAAC"}
@@ -1,13 +1,14 @@
1
1
  "use strict";
2
2
  Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.Microclimate = void 0;
4
- const SensorDevicesJsonSchema_1 = require("./datasources/SensorDevicesJsonSchema");
5
- const MeasurementsJsonSchema_1 = require("./datasources/MeasurementsJsonSchema");
6
- const SensorDevices_1 = require("./SensorDevices");
7
4
  const Measurements_1 = require("./Measurements");
5
+ const SensorDevices_1 = require("./SensorDevices");
8
6
  const SensorDevicesImport_1 = require("./SensorDevicesImport");
9
- const SensorPointsView_1 = require("./SensorPointsView");
10
7
  const SensorMeasurementsView_1 = require("./SensorMeasurementsView");
8
+ const SensorPointsView_1 = require("./SensorPointsView");
9
+ const MeasurementsJsonSchema_1 = require("./datasources/MeasurementsJsonSchema");
10
+ const SensorDevicesJsonSchema_1 = require("./datasources/SensorDevicesJsonSchema");
11
+ const SensorMeasurementsLatestView_1 = require("./SensorMeasurementsLatestView");
11
12
  const forExport = {
12
13
  name: "Microclimate",
13
14
  pgSchema: "microclimate",
@@ -21,6 +22,7 @@ const forExport = {
21
22
  sensorDevicesImport: SensorDevicesImport_1.sensorDevicesImport,
22
23
  sensorPointsView: SensorPointsView_1.sensorPointsView,
23
24
  sensorMeasurementsView: SensorMeasurementsView_1.sensorMeasurementsView,
25
+ sensorMeasurementsLatestView: SensorMeasurementsLatestView_1.sensorMeasurementsLatestView,
24
26
  },
25
27
  };
26
28
  exports.Microclimate = forExport;
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema-definitions/index.ts"],"names":[],"mappings":";;;AAAA,mFAAmF;AACnF,iFAAiF;AACjF,mDAAmD;AACnD,iDAAiD;AACjD,+DAA+D;AAC/D,yDAAyD;AACzD,qEAAqE;AAErE,MAAM,SAAS,GAAQ;IACnB,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,cAAc;IACxB,WAAW,EAAE;QACT,uBAAuB,EAAvB,iDAAuB;QACvB,sBAAsB,EAAtB,+CAAsB;KACzB;IACD,WAAW,EAAE;QACT,aAAa,EAAb,6BAAa;QACb,YAAY,EAAZ,2BAAY;QACZ,mBAAmB,EAAnB,yCAAmB;QACnB,gBAAgB,EAAhB,mCAAgB;QAChB,sBAAsB,EAAtB,+CAAsB;KACzB;CACJ,CAAC;AAEoB,iCAAY"}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/schema-definitions/index.ts"],"names":[],"mappings":";;;AAAA,iDAAiD;AACjD,mDAAmD;AACnD,+DAA+D;AAC/D,qEAAqE;AACrE,yDAAyD;AACzD,iFAAiF;AACjF,mFAAmF;AACnF,iFAA8E;AAE9E,MAAM,SAAS,GAAQ;IACnB,IAAI,EAAE,cAAc;IACpB,QAAQ,EAAE,cAAc;IACxB,WAAW,EAAE;QACT,uBAAuB,EAAvB,iDAAuB;QACvB,sBAAsB,EAAtB,+CAAsB;KACzB;IACD,WAAW,EAAE;QACT,aAAa,EAAb,6BAAa;QACb,YAAY,EAAZ,2BAAY;QACZ,mBAAmB,EAAnB,yCAAmB;QACnB,gBAAgB,EAAhB,mCAAgB;QAChB,sBAAsB,EAAtB,+CAAsB;QACtB,4BAA4B,EAA5B,2DAA4B;KAC/B;CACJ,CAAC;AAEoB,iCAAY"}
@@ -0,0 +1,8 @@
1
+ import { Model, ModelAttributes } from "@golemio/core/dist/shared/sequelize";
2
+ import { ILatestMeasurementDto } from "./interfaces/ILatestMeasurementDto";
3
+ export declare class SensorMeasurementsLatestViewModel extends Model<ILatestMeasurementDto> implements ILatestMeasurementDto {
4
+ point_id: number;
5
+ measure: string;
6
+ measured_at: Date;
7
+ static attributeModel: ModelAttributes<SensorMeasurementsLatestViewModel, ILatestMeasurementDto>;
8
+ }
@@ -0,0 +1,13 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.SensorMeasurementsLatestViewModel = void 0;
4
+ const sequelize_1 = require("@golemio/core/dist/shared/sequelize");
5
+ class SensorMeasurementsLatestViewModel extends sequelize_1.Model {
6
+ }
7
+ exports.SensorMeasurementsLatestViewModel = SensorMeasurementsLatestViewModel;
8
+ SensorMeasurementsLatestViewModel.attributeModel = {
9
+ point_id: { type: sequelize_1.DataTypes.INTEGER },
10
+ measure: { type: sequelize_1.DataTypes.TEXT },
11
+ measured_at: { type: sequelize_1.DataTypes.DATE },
12
+ };
13
+ //# sourceMappingURL=SensorMeasurementsLatestViewModel.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"SensorMeasurementsLatestViewModel.js","sourceRoot":"","sources":["../../../src/schema-definitions/models/SensorMeasurementsLatestViewModel.ts"],"names":[],"mappings":";;;AAAA,mEAAwF;AAGxF,MAAa,iCAAkC,SAAQ,iBAA4B;;AAAnF,8EAUC;AALiB,gDAAc,GAA8E;IACtG,QAAQ,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;IACrC,OAAO,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IACjC,WAAW,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;CACxC,CAAC"}
@@ -8,6 +8,5 @@ export declare class SensorMeasurementsViewModel extends Model<ISensorMeasuremen
8
8
  measure: string;
9
9
  value: number;
10
10
  unit: string;
11
- rn: number;
12
11
  static attributeModel: ModelAttributes<SensorMeasurementsViewModel, ISensorMeasurementsView>;
13
12
  }
@@ -13,6 +13,5 @@ SensorMeasurementsViewModel.attributeModel = {
13
13
  measure: { type: sequelize_1.DataTypes.TEXT },
14
14
  value: { type: sequelize_1.DataTypes.DOUBLE },
15
15
  unit: { type: sequelize_1.DataTypes.TEXT },
16
- rn: { type: sequelize_1.DataTypes.INTEGER },
17
16
  };
18
17
  //# sourceMappingURL=SensorMeasurementsViewModel.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"SensorMeasurementsViewModel.js","sourceRoot":"","sources":["../../../src/schema-definitions/models/SensorMeasurementsViewModel.ts"],"names":[],"mappings":";;;AAAA,mEAAwF;AAGxF,MAAa,2BAA4B,SAAQ,iBAA8B;;AAA/E,kEAoBC;AAViB,0CAAc,GAA0E;IAClG,SAAS,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;IACzC,WAAW,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IACrC,QAAQ,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;IACrC,WAAW,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;IACxC,OAAO,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IACjC,KAAK,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,MAAM,EAAE;IACjC,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IAC9B,EAAE,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;CAClC,CAAC"}
1
+ {"version":3,"file":"SensorMeasurementsViewModel.js","sourceRoot":"","sources":["../../../src/schema-definitions/models/SensorMeasurementsViewModel.ts"],"names":[],"mappings":";;;AAAA,mEAAwF;AAGxF,MAAa,2BAA4B,SAAQ,iBAA8B;;AAA/E,kEAkBC;AATiB,0CAAc,GAA0E;IAClG,SAAS,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,MAAM,CAAC,EAAE,CAAC,EAAE;IACzC,WAAW,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IACrC,QAAQ,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;IACrC,WAAW,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,OAAO,EAAE;IACxC,OAAO,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;IACjC,KAAK,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,MAAM,EAAE;IACjC,IAAI,EAAE,EAAE,IAAI,EAAE,qBAAS,CAAC,IAAI,EAAE;CACjC,CAAC"}
@@ -0,0 +1,5 @@
1
+ export interface ILatestMeasurementDto {
2
+ point_id: number;
3
+ measure: string;
4
+ measured_at: Date;
5
+ }
@@ -0,0 +1,3 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ //# sourceMappingURL=ILatestMeasurementDto.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ILatestMeasurementDto.js","sourceRoot":"","sources":["../../../../src/schema-definitions/models/interfaces/ILatestMeasurementDto.ts"],"names":[],"mappings":""}
@@ -63,6 +63,7 @@ Modul slouží k ukládání a poskytování informací o microclimatu.
63
63
  - SensorDevicesRepository ('sensorAddr' pro message na závislé fronty)
64
64
  - závislé fronty (do kterých jsou odesílány zprávy z metody workeru)
65
65
  - název: dataplatform.microclimate.refreshMeasurementsById
66
+ - název: dataplatform.microclimate.refreshSensorViews
66
67
 
67
68
  #### _task: RefreshMeasurementsByIdTask_
68
69
 
@@ -73,12 +74,30 @@ Modul slouží k ukládání a poskytování informací o microclimatu.
73
74
  - transformace
74
75
  - [SensorDevicesTransformation.ts](https://gitlab.com/operator-ict/golemio/code/modules/microclimate/-/blob/development/src/integration-engine/transformations/SensorDevicesTransformation.ts) - mapování pro `MeasurementsRepository`
75
76
 
77
+ #### _task: RefreshSensorViewsTask_
78
+
79
+ - vstupní rabbitmq fronta
80
+ - název: dataplatform.microclimate.refreshSensorViews
81
+ - TTL: 10 minut
82
+ - parametry: žádné
83
+ - závislé fronty (do kterých jsou odesílány zprávy z metody workeru)
84
+ - žádné
85
+ - datové zdroje
86
+ - žádné
87
+ - transformace
88
+ - žádné
89
+ - data modely
90
+ - SensorPointsHeightsViewModel `v_sensor_points_heights`
91
+ - SensorMeasurementsViewModel `v_sensor_measurements`
92
+ - SensorMeasurementsLatestViewModel `v_sensor_measurements_latest`
93
+
76
94
  ## Uložení dat
77
95
 
78
96
  - typ databáze
79
97
  - PSQL
80
98
  - databázové schéma
81
99
  - ![microclimate er diagram](./assets/microclimate_erd.png)
100
+ - ![microclimate measurements views er diagram](./assets/microclimate_measure_views_erd.png)
82
101
 
83
102
  # Popis Integraci datovych sad podle initial issue
84
103
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@golemio/microclimate",
3
- "version": "1.2.0",
3
+ "version": "1.2.1-dev.1133205826",
4
4
  "description": "Golemio Microclimate Module",
5
5
  "main": "dist/index.js",
6
6
  "types": "dist/index.d.ts",
@@ -34,7 +34,7 @@
34
34
  "@commitlint/cli": "^11.0.0",
35
35
  "@commitlint/config-conventional": "^11.0.0",
36
36
  "@golemio/cli": "1.5.0",
37
- "@golemio/core": "1.9.2",
37
+ "@golemio/core": "1.9.6",
38
38
  "@golemio/db-common": "1.1.2",
39
39
  "@golemio/eslint-config": "1.1.1",
40
40
  "@types/chai": "4.2.3",