@golemio/pid 2.0.10-dev.372675355 → 2.0.11-dev.373518907

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 (50) hide show
  1. package/dist/integration-engine/queueDefinitions.js +5 -25
  2. package/dist/integration-engine/queueDefinitions.js.map +1 -1
  3. package/dist/integration-engine/ropid-gtfs/RopidGTFSMetadataModel.d.ts +9 -2
  4. package/dist/integration-engine/ropid-gtfs/RopidGTFSMetadataModel.js +39 -21
  5. package/dist/integration-engine/ropid-gtfs/RopidGTFSMetadataModel.js.map +1 -1
  6. package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.d.ts +34 -18
  7. package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js +300 -269
  8. package/dist/integration-engine/ropid-gtfs/RopidGTFSWorker.js.map +1 -1
  9. package/dist/integration-engine/ropid-gtfs/index.d.ts +4 -4
  10. package/dist/integration-engine/ropid-gtfs/index.js +4 -4
  11. package/dist/integration-engine/ropid-gtfs/index.js.map +1 -1
  12. package/dist/integration-engine/ropid-gtfs/{RopidDeparturesPresetsTransformation.d.ts → transformations/RopidDeparturesPresetsTransformation.d.ts} +1 -1
  13. package/dist/integration-engine/ropid-gtfs/{RopidDeparturesPresetsTransformation.js → transformations/RopidDeparturesPresetsTransformation.js} +1 -1
  14. package/dist/integration-engine/ropid-gtfs/transformations/RopidDeparturesPresetsTransformation.js.map +1 -0
  15. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSCisStopsTransformation.d.ts +25 -0
  16. package/dist/integration-engine/ropid-gtfs/{RopidGTFSCisStopsTransformation.js → transformations/RopidGTFSCisStopsTransformation.js} +25 -7
  17. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSCisStopsTransformation.js.map +1 -0
  18. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSOisTransformation.d.ts +15 -0
  19. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSOisTransformation.js +38 -0
  20. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSOisTransformation.js.map +1 -0
  21. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSRunNumbersTransformation.d.ts +15 -0
  22. package/dist/integration-engine/ropid-gtfs/{RopidGTFSRunNumbersTransformation.js → transformations/RopidGTFSRunNumbersTransformation.js} +14 -6
  23. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSRunNumbersTransformation.js.map +1 -0
  24. package/dist/integration-engine/ropid-gtfs/{RopidGTFSTransformation.d.ts → transformations/RopidGTFSTransformation.d.ts} +5 -4
  25. package/dist/integration-engine/ropid-gtfs/{RopidGTFSTransformation.js → transformations/RopidGTFSTransformation.js} +8 -12
  26. package/dist/integration-engine/ropid-gtfs/transformations/RopidGTFSTransformation.js.map +1 -0
  27. package/dist/output-gateway/ropid-gtfs/models/GTFSStopModel.js +3 -5
  28. package/dist/output-gateway/ropid-gtfs/models/GTFSStopModel.js.map +1 -1
  29. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStopGroups.d.ts +143 -0
  30. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStopGroups.js +91 -0
  31. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStopGroups.js.map +1 -0
  32. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStops.d.ts +119 -0
  33. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStops.js +82 -0
  34. package/dist/schema-definitions/ropid-gtfs/RopidGTFSCisStops.js.map +1 -0
  35. package/dist/schema-definitions/ropid-gtfs/RopidGTFSOisMapping.d.ts +60 -0
  36. package/dist/schema-definitions/ropid-gtfs/RopidGTFSOisMapping.js +76 -0
  37. package/dist/schema-definitions/ropid-gtfs/RopidGTFSOisMapping.js.map +1 -0
  38. package/dist/schema-definitions/ropid-gtfs/RopidGTFSRunNumbers.d.ts +18 -2
  39. package/dist/schema-definitions/ropid-gtfs/RopidGTFSRunNumbers.js +2 -2
  40. package/dist/schema-definitions/ropid-gtfs/RopidGTFSRunNumbers.js.map +1 -1
  41. package/dist/schema-definitions/ropid-gtfs/index.d.ts +262 -18
  42. package/dist/schema-definitions/ropid-gtfs/index.js +7 -91
  43. package/dist/schema-definitions/ropid-gtfs/index.js.map +1 -1
  44. package/package.json +1 -1
  45. package/dist/integration-engine/ropid-gtfs/RopidDeparturesPresetsTransformation.js.map +0 -1
  46. package/dist/integration-engine/ropid-gtfs/RopidGTFSCisStopsTransformation.d.ts +0 -10
  47. package/dist/integration-engine/ropid-gtfs/RopidGTFSCisStopsTransformation.js.map +0 -1
  48. package/dist/integration-engine/ropid-gtfs/RopidGTFSRunNumbersTransformation.d.ts +0 -7
  49. package/dist/integration-engine/ropid-gtfs/RopidGTFSRunNumbersTransformation.js.map +0 -1
  50. package/dist/integration-engine/ropid-gtfs/RopidGTFSTransformation.js.map +0 -1
@@ -20,7 +20,7 @@ var __rest = (this && this.__rest) || function (s, e) {
20
20
  return t;
21
21
  };
22
22
  Object.defineProperty(exports, "__esModule", { value: true });
23
- exports.RopidGTFSWorker = void 0;
23
+ exports.RopidGTFSWorker = exports.datasetFileModelMap = void 0;
24
24
  const golemio_errors_1 = require("@golemio/core/dist/shared/golemio-errors");
25
25
  const golemio_validator_1 = require("@golemio/core/dist/shared/golemio-validator");
26
26
  const config_1 = require("@golemio/core/dist/integration-engine/config");
@@ -34,9 +34,40 @@ const ropid_gtfs_1 = require("../../schema-definitions/ropid-gtfs");
34
34
  const ropid_departures_presets_1 = require("../../schema-definitions/ropid-departures-presets");
35
35
  const pg_copy_streams_1 = require("pg-copy-streams");
36
36
  const vehicle_positions_1 = require("../../schema-definitions/vehicle-positions");
37
- const isCachedFileMeta = (obj) => {
38
- return obj instanceof Object && obj.filepath !== undefined && obj.name !== undefined && obj.data === undefined;
37
+ const RopidGTFSOisTransformation_1 = require("./transformations/RopidGTFSOisTransformation");
38
+ var CacheContentType;
39
+ (function (CacheContentType) {
40
+ CacheContentType["CSV"] = "CSV";
41
+ CacheContentType["JSON"] = "JSON";
42
+ })(CacheContentType || (CacheContentType = {}));
43
+ const isCachedDataset = (obj) => {
44
+ return (obj instanceof Object &&
45
+ obj.filepath !== undefined &&
46
+ obj.name !== undefined &&
47
+ obj.dataset !== undefined &&
48
+ obj.data === undefined);
39
49
  };
50
+ const datasetFileModelMap = (dataset, name) => {
51
+ let model;
52
+ switch (dataset) {
53
+ case _1.DatasetEnum.PID_GTFS:
54
+ model = name;
55
+ break;
56
+ case _1.DatasetEnum.RUN_NUMBERS:
57
+ model = "run_numbers";
58
+ break;
59
+ case _1.DatasetEnum.OIS_MAPPING:
60
+ model = "ois";
61
+ break;
62
+ case _1.DatasetEnum.CIS_STOPS:
63
+ model = ["cis_stops", "cis_stop_groups"];
64
+ break;
65
+ default:
66
+ throw new Error(`Error mapping dataset ${dataset} and source ${name}`);
67
+ }
68
+ return model;
69
+ };
70
+ exports.datasetFileModelMap = datasetFileModelMap;
40
71
  class RopidGTFSWorker extends workers_1.BaseWorker {
41
72
  constructor() {
42
73
  super();
@@ -44,138 +75,211 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
44
75
  * Queue listener method - triggers entire flow
45
76
  */
46
77
  this.checkForNewData = () => __awaiter(this, void 0, void 0, function* () {
47
- // checking PID_GTFS dataset
48
- const serverLastModified = yield this.dataSource.getLastModified();
49
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.PID_GTFS);
50
- if (serverLastModified !== dbLastModified.lastModified) {
51
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadFiles", "Just do it!");
78
+ const datasets = [];
79
+ for (const dataset of Object.keys(this.datasetMap)) {
80
+ const serverLastModified = this.datasetMap[dataset].datasource.getLastModified();
81
+ const dbLastModified = yield this.metaModel.getLastModified(dataset);
82
+ if (serverLastModified !== dbLastModified.lastModified) {
83
+ datasets.push(dataset);
84
+ }
52
85
  }
53
- // checking CIS_STOPS dataset
54
- const CISserverLastModified = yield this.dataSourceCisStops.getLastModified();
55
- const CISdbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.CIS_STOPS);
56
- if (CISserverLastModified !== CISdbLastModified.lastModified) {
57
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadCisStops", "Just do it!");
86
+ if (datasets.length && datasets.length !== Object.keys(this.datasetMap).length) {
87
+ helpers_1.log.error(`RopidGTFS datasets are out of sync`);
58
88
  }
59
- // checking RUN_NUMBERS dataset
60
- const runNumbersServerLastModified = yield this.dataSourceRunNumbers.getLastModified();
61
- const runNumbersDbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.RUN_NUMBERS);
62
- if (runNumbersServerLastModified !== runNumbersDbLastModified.lastModified) {
63
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadRunNumbers", "Just do it!");
89
+ if (datasets.length) {
90
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadDatasets", JSON.stringify(datasets));
91
+ }
92
+ else {
93
+ helpers_1.log.info(`RopidGTFS datasets are up to date.`);
64
94
  }
65
95
  });
66
96
  /**
67
- * Queue listener method - triggers for new presets only
97
+ * Queue listener method - triggers dataset download
98
+ * @param {object} msg
99
+ * @param {Buffer} msg.content - array of dataset names, empty to force downloading all
68
100
  */
69
- this.checkForNewDeparturesPresets = () => __awaiter(this, void 0, void 0, function* () {
70
- // checking DEPARTURES_PRESETS dataset
71
- const departuresPresetsServerLastModified = yield this.dataSourceDeparturesPresets.getLastModified();
72
- const departuresPresetsDbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.DEPARTURES_PRESETS);
73
- if (departuresPresetsServerLastModified !== departuresPresetsDbLastModified.lastModified) {
74
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadDeparturesPresets", "Just do it!");
101
+ this.downloadDatasets = (msg) => __awaiter(this, void 0, void 0, function* () {
102
+ let datasets;
103
+ try {
104
+ const content = msg.content.toString();
105
+ if (content) {
106
+ datasets = JSON.parse(content);
107
+ this.validateDatasetNames(datasets);
108
+ }
109
+ else {
110
+ // utility setup - force run all if message empty
111
+ datasets = Object.keys(this.datasetMap);
112
+ }
113
+ }
114
+ catch (err) {
115
+ throw new golemio_errors_1.CustomError("Error while parsing input data", true, this.constructor.name, undefined, err);
75
116
  }
117
+ helpers_1.log.debug(`Downloading datasets: ${datasets}`);
118
+ let transformMessages = [];
119
+ for (const dataset of datasets) {
120
+ transformMessages = transformMessages.concat(yield this.downloadAndPersistDatasetFiles(dataset));
121
+ }
122
+ yield Promise.all(transformMessages.map((msg) => __awaiter(this, void 0, void 0, function* () {
123
+ return this.sendMessageToExchange("workers." + this.queuePrefix + ".transformAndSaveData", JSON.stringify(msg));
124
+ })));
125
+ /**
126
+ * TODO remove sleep here, add meta state processing to above loop
127
+ * for checkSavedRowsAndReplaceTables not to pass without action
128
+ **/
129
+ yield new Promise((done) => setTimeout(done, 5 * 60 * 1000)); // sleeps for 5 minutes
130
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".checkSavedRowsAndReplaceTables", JSON.stringify(datasets));
76
131
  });
77
132
  /**
78
- * Queue listener method - triggers processing of PID_GTFS dataset
133
+ * Helper method - download and persist dataset
79
134
  */
80
- this.downloadFiles = () => __awaiter(this, void 0, void 0, function* () {
81
- const files = yield this.dataSource.getAll();
82
- const cachedFileMeta = yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () {
135
+ this.downloadAndPersistDatasetFiles = (dataset) => __awaiter(this, void 0, void 0, function* () {
136
+ helpers_1.log.debug(`Processing datasets: ${dataset}`);
137
+ let files = yield this.datasetMap[dataset].datasource.getAll();
138
+ if (!Array.isArray(files))
139
+ files = [files];
140
+ const dbLastModified = yield this.metaModel.getLastModified(dataset);
141
+ const cachedDataset = yield Promise.all(files.map((file) => __awaiter(this, void 0, void 0, function* () {
142
+ helpers_1.log.debug(`Processing datasets file: ${JSON.stringify(file.name)}`);
83
143
  const { data } = file, meta = __rest(file, ["data"]);
84
- yield this.redisModel.hset(file.filepath, data);
85
- return Object.assign({}, meta);
144
+ yield this.redisModel.hset(file.filepath, typeof data === "string" ? data : JSON.stringify(data));
145
+ const key = exports.datasetFileModelMap(dataset, file.name);
146
+ const metaState = (Array.isArray(key) ? key : [key]).map((name) => {
147
+ return {
148
+ dataset,
149
+ key: name,
150
+ type: _1.MetaTypeEnum.STATE,
151
+ value: _1.MetaStateEnum.DOWNLOADED,
152
+ version: dbLastModified.version + 1,
153
+ };
154
+ });
155
+ yield this.metaModel.save(metaState);
156
+ return Object.assign(Object.assign({}, meta), { dataset });
86
157
  })));
87
- const lastModified = yield this.dataSource.getLastModified();
88
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.PID_GTFS);
158
+ const lastModified = yield this.datasetMap[dataset].datasource.getLastModified();
89
159
  yield this.metaModel.save({
90
- dataset: _1.DatasetEnum.PID_GTFS,
160
+ dataset,
91
161
  key: _1.MetaDatasetInfoKeyEnum.LAST_MODIFIED,
92
162
  type: _1.MetaTypeEnum.DATASET_INFO,
93
163
  value: lastModified,
94
- version: dbLastModified.version + 1 || 1,
164
+ version: dbLastModified.version + 1,
95
165
  });
96
- // send messages for transformation
97
- const promises = cachedFileMeta.map((file) => __awaiter(this, void 0, void 0, function* () {
98
- // save meta
99
- yield this.metaModel.save({
100
- dataset: _1.DatasetEnum.PID_GTFS,
101
- key: file.name,
102
- type: _1.MetaTypeEnum.STATE,
103
- value: _1.MetaStateEnum.DOWNLOADED,
104
- version: dbLastModified.version + 1 || 1,
105
- });
106
- return this.sendMessageToExchange("workers." + this.queuePrefix + ".transformAndSaveData", JSON.stringify(file));
107
- }));
108
- yield Promise.all(promises);
109
- // sleep 5 minute send checkSavedRowsAndReplaceTables
110
- yield new Promise((done) => setTimeout(done, 5 * 60 * 1000));
111
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".checkSavedRowsAndReplaceTables", "Just do it!");
166
+ helpers_1.log.debug(`Processing datasets: ${dataset} finished: ${JSON.stringify(cachedDataset)}`);
167
+ return cachedDataset;
168
+ });
169
+ /**
170
+ * Queue listener method - triggers for new presets only
171
+ */
172
+ this.checkForNewDeparturesPresets = () => __awaiter(this, void 0, void 0, function* () {
173
+ // checking DEPARTURES_PRESETS dataset
174
+ const departuresPresetsServerLastModified = yield this.dataSourceDeparturesPresets.getLastModified();
175
+ const departuresPresetsDbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.DEPARTURES_PRESETS);
176
+ if (departuresPresetsServerLastModified !== departuresPresetsDbLastModified.lastModified) {
177
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadDeparturesPresets", "Just do it!");
178
+ }
112
179
  });
113
180
  /**
114
- * Queue listener method - transform and save PID_GTFS dataset to tmp
181
+ * Queue listener method - transform and save dataset item to tmp
115
182
  */
116
183
  this.transformAndSaveData = (msg) => __awaiter(this, void 0, void 0, function* () {
117
184
  let inputData;
118
185
  try {
119
186
  inputData = JSON.parse(msg.content.toString());
120
- if (!isCachedFileMeta(inputData)) {
187
+ if (!isCachedDataset(inputData)) {
121
188
  throw new Error("Input data has invalid format.");
122
189
  }
123
190
  }
124
191
  catch (err) {
125
192
  throw new golemio_errors_1.CustomError("Error while parsing input data", true, this.constructor.name, undefined, err);
126
193
  }
127
- inputData.data = yield this.redisModel.hget(inputData.filepath);
128
- const transformedData = yield this.transformation.transform(inputData);
129
- const model = this.getModelByName(transformedData.name);
194
+ let data = this.datasetMap[inputData.dataset].cacheContentType === CacheContentType.JSON
195
+ ? JSON.parse(yield this.redisModel.hget(inputData.filepath))
196
+ : yield this.redisModel.hget(inputData.filepath);
197
+ const transformedDataset = yield this.datasetMap[inputData.dataset].transformation.transform({
198
+ data,
199
+ name: inputData.name,
200
+ });
201
+ if (inputData.dataset === _1.DatasetEnum.CIS_STOPS) {
202
+ const modelName = exports.datasetFileModelMap(inputData.dataset, inputData.name);
203
+ yield this.saveTransformedDataset(transformedDataset.cis_stops, inputData.dataset, modelName[0]);
204
+ yield this.saveTransformedDataset(transformedDataset.cis_stop_groups, inputData.dataset, modelName[1]);
205
+ }
206
+ else {
207
+ const modelName = exports.datasetFileModelMap(inputData.dataset, inputData.name);
208
+ yield this.saveTransformedDataset(transformedDataset, inputData.dataset, modelName);
209
+ }
210
+ });
211
+ this.saveTransformedDataset = (transformedData, dataset, modelName) => __awaiter(this, void 0, void 0, function* () {
212
+ const model = this.getModelByName(modelName);
130
213
  yield (model === null || model === void 0 ? void 0 : model.truncate(true));
131
- yield this.saveDataToTmp(transformedData);
132
- // update meta
133
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.PID_GTFS);
134
- yield this.metaModel.updateState(_1.DatasetEnum.PID_GTFS, transformedData.name, _1.MetaStateEnum.SAVED, dbLastModified.version);
214
+ switch (dataset) {
215
+ case _1.DatasetEnum.PID_GTFS:
216
+ yield this.streamDataToTmp(transformedData, modelName);
217
+ break;
218
+ default:
219
+ yield (model === null || model === void 0 ? void 0 : model.save(transformedData, true));
220
+ helpers_1.log.debug(`Copying finished. (${modelName})`);
221
+ }
222
+ const dbLastModified = yield this.metaModel.getLastModified(dataset);
223
+ yield this.metaModel.updateState(dataset, modelName, _1.MetaStateEnum.SAVED, dbLastModified.version);
135
224
  });
136
225
  /**
137
226
  * Queue listener method - verify tmp tables and replace public
138
227
  */
139
- this.checkSavedRowsAndReplaceTables = () => __awaiter(this, void 0, void 0, function* () {
140
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.PID_GTFS);
141
- const alreadyDeployed = yield this.metaModel.checkIfNewVersionIsAlreadyDeployed(_1.DatasetEnum.PID_GTFS, dbLastModified.version);
142
- if (alreadyDeployed) {
228
+ this.checkSavedRowsAndReplaceTables = (msg) => __awaiter(this, void 0, void 0, function* () {
229
+ let datasets;
230
+ try {
231
+ datasets = JSON.parse(msg.content.toString());
232
+ this.validateDatasetNames(datasets);
233
+ }
234
+ catch (err) {
235
+ throw new golemio_errors_1.CustomError("Error while parsing input data", true, this.constructor.name, undefined, err);
236
+ }
237
+ const datasetDeployInfo = yield Promise.all(datasets.map((dataset) => __awaiter(this, void 0, void 0, function* () {
238
+ const lastModified = yield this.metaModel.getLastModified(dataset);
239
+ const isDeployed = yield this.metaModel.checkIfNewVersionIsAlreadyDeployed(dataset, lastModified.version);
240
+ return { dataset, lastModified, isDeployed };
241
+ })));
242
+ helpers_1.log.debug(`Datasets status: ${JSON.stringify(datasetDeployInfo)}`);
243
+ const notDeployed = datasetDeployInfo.filter((info) => !info.isDeployed);
244
+ if (datasets.length !== notDeployed.length) {
245
+ const names = notDeployed.map((el) => el.dataset);
246
+ helpers_1.log.error(`Error while synchronized download of datasets: [${names}] of [${datasets}] deployed already`);
247
+ }
248
+ if (!notDeployed.length) {
249
+ helpers_1.log.debug(`Datasets status: already deployed`);
143
250
  return true;
144
251
  }
145
- const allSaved = yield this.metaModel.checkAllTablesHasSavedState(_1.DatasetEnum.PID_GTFS, dbLastModified.version);
252
+ const notDeployedVersions = notDeployed.map((el) => ({ dataset: el.dataset, version: el.lastModified.version }));
253
+ const allSaved = yield this.metaModel.checkAllTablesHasSavedState(notDeployedVersions);
146
254
  try {
147
255
  if (!allSaved) {
148
256
  // wait to the saving process
149
- helpers_1.log.debug("checkSavedRowsAndReplaceTables - not ready yet");
257
+ helpers_1.log.debug("Datasets status: not ready yet");
150
258
  yield new Promise((done) => setTimeout(done, 5 * 60 * 1000)); // sleeps for 5 minutes
151
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".checkSavedRowsAndReplaceTables", "Just do it!");
259
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".checkSavedRowsAndReplaceTables", JSON.stringify(datasets));
152
260
  helpers_1.log.debug("checkSavedRowsAndReplaceTables - new message was resent");
153
261
  return true;
154
262
  }
155
- yield this.metaModel.replaceTables(_1.DatasetEnum.PID_GTFS, dbLastModified.version);
263
+ yield this.metaModel.replaceTables(notDeployedVersions);
156
264
  yield this.redisModel.truncate();
157
265
  yield this.delayComputationTripsModel.truncate();
158
266
  yield this.runTripsModel.truncate();
159
267
  yield this.metaModel.refreshMaterializedViews();
160
- // save meta
161
- yield this.metaModel.save({
162
- dataset: _1.DatasetEnum.PID_GTFS,
163
- key: _1.MetaDatasetInfoKeyEnum.DEPLOYED,
164
- type: _1.MetaTypeEnum.DATASET_INFO,
165
- value: "true",
166
- version: dbLastModified.version,
167
- });
168
268
  return true;
169
269
  }
170
270
  catch (err) {
171
271
  // log failed saving process
172
- yield this.metaModel.rollbackFailedSaving(_1.DatasetEnum.PID_GTFS, dbLastModified.version);
272
+ yield Promise.all(notDeployedVersions.map((el) => __awaiter(this, void 0, void 0, function* () {
273
+ yield this.metaModel.rollbackFailedSaving(el.dataset, el.version);
274
+ })));
173
275
  // check number of tries
174
- const retry = yield this.metaModel.getNumberOfDownloadRetries(_1.DatasetEnum.PID_GTFS, dbLastModified.version);
175
- if (retry <= 5) {
276
+ const retries = yield Promise.all(notDeployedVersions.map((el) => __awaiter(this, void 0, void 0, function* () {
277
+ return yield this.metaModel.getNumberOfDownloadRetries(el.dataset, el.version);
278
+ })));
279
+ if (Math.min(...retries) <= 5) {
176
280
  // send new downloadFiles, log it and finish
177
- yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadFiles", "Just do it!");
178
- helpers_1.IntegrationErrorHandler.handle(new golemio_errors_1.CustomError(`Error while checking RopidGTFS saved rows. Attempt number ${retry} was resent.`, true, this.constructor.name, 5004, err));
281
+ yield this.sendMessageToExchange("workers." + this.queuePrefix + ".downloadDatasets", JSON.stringify(datasets));
282
+ helpers_1.IntegrationErrorHandler.handle(new golemio_errors_1.CustomError(`Error while checking RopidGTFS saved rows. Attempt number ${Math.min(...retries)} was resent.`, true, this.constructor.name, 5004, err));
179
283
  return true;
180
284
  }
181
285
  else {
@@ -184,123 +288,6 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
184
288
  }
185
289
  }
186
290
  });
187
- /**
188
- * Queue listener method - triggers processing of CIS_STOPS dataset
189
- */
190
- this.downloadCisStops = () => __awaiter(this, void 0, void 0, function* () {
191
- const file = yield this.dataSourceCisStops.getAll();
192
- const lastModified = yield this.dataSourceCisStops.getLastModified();
193
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.CIS_STOPS);
194
- yield this.metaModel.save({
195
- dataset: _1.DatasetEnum.CIS_STOPS,
196
- key: _1.MetaDatasetInfoKeyEnum.LAST_MODIFIED,
197
- type: _1.MetaTypeEnum.DATASET_INFO,
198
- value: lastModified,
199
- version: dbLastModified.version + 1,
200
- });
201
- const transformedData = yield this.transformationCisStops.transform(file.data);
202
- // duplicity checking
203
- // TODO is it ok if all duplicate items are removed?
204
- const uniqueMap = new Map();
205
- const duplicateCisStopGroups = [];
206
- transformedData.cis_stop_groups.forEach((item) => {
207
- if (uniqueMap.has(item.cis)) {
208
- duplicateCisStopGroups.push(item.cis);
209
- uniqueMap.delete(item.cis);
210
- }
211
- else {
212
- uniqueMap.set(item.cis, item);
213
- }
214
- });
215
- const uniqueCisStopGroups = [...uniqueMap.values()];
216
- if (duplicateCisStopGroups.length > 0) {
217
- helpers_1.log.warn("CIS_STOP_GROUPS contains duplicate cis. Items with this cis was removed: " +
218
- JSON.stringify(duplicateCisStopGroups));
219
- }
220
- // save meta
221
- yield this.metaModel.save([
222
- {
223
- dataset: _1.DatasetEnum.CIS_STOPS,
224
- key: "cis_stop_groups",
225
- type: _1.MetaTypeEnum.TABLE_TOTAL_COUNT,
226
- value: uniqueCisStopGroups.length,
227
- version: dbLastModified.version + 1,
228
- },
229
- {
230
- dataset: _1.DatasetEnum.CIS_STOPS,
231
- key: "cis_stops",
232
- type: _1.MetaTypeEnum.TABLE_TOTAL_COUNT,
233
- value: transformedData.cis_stops.length,
234
- version: dbLastModified.version + 1,
235
- },
236
- ]);
237
- try {
238
- yield this.cisStopGroupsModel.truncate(true);
239
- yield this.cisStopGroupsModel.save(uniqueCisStopGroups, true);
240
- yield this.metaModel.save({
241
- dataset: _1.DatasetEnum.CIS_STOPS,
242
- key: "cis_stop_groups",
243
- type: _1.MetaTypeEnum.STATE,
244
- value: _1.MetaStateEnum.SAVED,
245
- version: dbLastModified.version + 1 || 1,
246
- });
247
- yield this.cisStopsModel.truncate(true);
248
- yield this.cisStopsModel.save(transformedData.cis_stops, true);
249
- yield this.metaModel.save({
250
- dataset: _1.DatasetEnum.CIS_STOPS,
251
- key: "cis_stops",
252
- type: _1.MetaTypeEnum.STATE,
253
- value: _1.MetaStateEnum.SAVED,
254
- version: dbLastModified.version + 1 || 1,
255
- });
256
- yield this.metaModel.checkSavedRows(_1.DatasetEnum.CIS_STOPS, dbLastModified.version + 1);
257
- yield this.metaModel.replaceTables(_1.DatasetEnum.CIS_STOPS, dbLastModified.version + 1);
258
- }
259
- catch (err) {
260
- helpers_1.log.error(err);
261
- yield this.metaModel.rollbackFailedSaving(_1.DatasetEnum.CIS_STOPS, dbLastModified.version + 1);
262
- }
263
- });
264
- /**
265
- * Queue listener method - triggers processing of RUN_NUMBERS dataset
266
- */
267
- this.downloadRunNumbers = () => __awaiter(this, void 0, void 0, function* () {
268
- const file = yield this.dataSourceRunNumbers.getAll();
269
- const lastModified = yield this.dataSourceRunNumbers.getLastModified();
270
- const dbLastModified = yield this.metaModel.getLastModified(_1.DatasetEnum.RUN_NUMBERS);
271
- yield this.metaModel.save({
272
- dataset: _1.DatasetEnum.RUN_NUMBERS,
273
- key: _1.MetaDatasetInfoKeyEnum.LAST_MODIFIED,
274
- type: _1.MetaTypeEnum.DATASET_INFO,
275
- value: lastModified,
276
- version: dbLastModified.version + 1,
277
- });
278
- const transformedData = yield this.transformationRunNumbers.transform(file.data);
279
- yield this.metaModel.save({
280
- dataset: _1.DatasetEnum.RUN_NUMBERS,
281
- key: "runNumbers",
282
- type: _1.MetaTypeEnum.TABLE_TOTAL_COUNT,
283
- value: transformedData.length,
284
- version: dbLastModified.version + 1,
285
- });
286
- try {
287
- yield this.runNumbersModel.truncate(true);
288
- yield this.runNumbersModel.save(transformedData, true);
289
- yield this.metaModel.save({
290
- dataset: _1.DatasetEnum.RUN_NUMBERS,
291
- key: "runNumbers",
292
- type: _1.MetaTypeEnum.STATE,
293
- value: _1.MetaStateEnum.SAVED,
294
- version: dbLastModified.version + 1 || 1,
295
- });
296
- yield this.metaModel.checkSavedRows(_1.DatasetEnum.RUN_NUMBERS, dbLastModified.version + 1);
297
- yield this.metaModel.replaceTables(_1.DatasetEnum.RUN_NUMBERS, dbLastModified.version + 1);
298
- }
299
- catch (err) {
300
- helpers_1.log.error(err);
301
- yield this.metaModel.rollbackFailedSaving(_1.DatasetEnum.RUN_NUMBERS, dbLastModified.version + 1);
302
- }
303
- });
304
291
  /**
305
292
  * Queue listener method - triggers processing of DEPARTURES_PRESETS dataset
306
293
  */
@@ -331,21 +318,48 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
331
318
  key: "departuresPresets",
332
319
  type: _1.MetaTypeEnum.STATE,
333
320
  value: _1.MetaStateEnum.SAVED,
334
- version: dbLastModified.version + 1 || 1,
321
+ version: dbLastModified.version + 1,
335
322
  });
336
323
  yield this.metaModel.checkSavedRows(_1.DatasetEnum.DEPARTURES_PRESETS, dbLastModified.version + 1);
337
- yield this.metaModel.replaceTables(_1.DatasetEnum.DEPARTURES_PRESETS, dbLastModified.version + 1);
324
+ yield this.metaModel.replaceTables([
325
+ { dataset: _1.DatasetEnum.DEPARTURES_PRESETS, version: dbLastModified.version + 1 },
326
+ ]);
338
327
  }
339
328
  catch (err) {
340
329
  helpers_1.log.error(err);
341
330
  yield this.metaModel.rollbackFailedSaving(_1.DatasetEnum.DEPARTURES_PRESETS, dbLastModified.version + 1);
342
331
  }
343
332
  });
344
- this.saveDataToTmp = (data) => __awaiter(this, void 0, void 0, function* () {
333
+ /**
334
+ * Validate dataset list against dataset enum
335
+ *
336
+ * @param {string[]} names - names of datasets
337
+ */
338
+ this.validateDatasetNames = (names) => {
339
+ if (!Array.isArray(names)) {
340
+ throw new Error(`Error validating dataset list: must be an array`);
341
+ }
342
+ if (!names.length) {
343
+ throw new Error(`Error validating dataset list: got empty array`);
344
+ }
345
+ const invalidNames = names.filter((name) => !this.validateDatasetName(name));
346
+ if (invalidNames.length) {
347
+ throw new Error(`Error validating dataset list: "${invalidNames.toString()}" is invalid`);
348
+ }
349
+ };
350
+ /**
351
+ * Validate name against dataset enum
352
+ *
353
+ * @param {string} name - name of datasets
354
+ */
355
+ this.validateDatasetName = (name) => {
356
+ return Object.keys(this.datasetMap).includes(name);
357
+ };
358
+ this.streamDataToTmp = (data, modelName) => __awaiter(this, void 0, void 0, function* () {
345
359
  // get connection and db client
346
360
  const connection = connectors_1.PostgresConnector.getConnection();
347
361
  const client = (yield connection.connectionManager.getConnection({ type: "write" }));
348
- const tmpTableName = "tmp." + ropid_gtfs_1.RopidGTFS[data.name].pgTableName;
362
+ const tmpTableName = "tmp." + ropid_gtfs_1.RopidGTFS[modelName].pgTableName;
349
363
  // copy transformed data to tmp table by stream
350
364
  yield new Promise((resolve, reject) => {
351
365
  const stream = client
@@ -356,42 +370,25 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
356
370
  return reject(err);
357
371
  }))
358
372
  .on("finish", () => __awaiter(this, void 0, void 0, function* () {
359
- helpers_1.log.debug(`Copying finished. (${data.name})`);
373
+ helpers_1.log.debug(`Copying finished. (${modelName})`);
360
374
  yield connection.connectionManager.releaseConnection(client);
361
375
  return resolve();
362
376
  }));
363
- data.data.pipe(stream);
377
+ data.pipe(stream);
364
378
  });
365
379
  });
366
380
  this.getModelByName = (name) => {
367
- if (ropid_gtfs_1.RopidGTFS[name].name) {
368
- return new models_1.PostgresModel(ropid_gtfs_1.RopidGTFS[name].name + "Model", {
369
- hasTmpTable: true,
370
- outputSequelizeAttributes: ropid_gtfs_1.RopidGTFS[name].outputSequelizeAttributes,
371
- pgTableName: ropid_gtfs_1.RopidGTFS[name].pgTableName,
372
- savingType: "insertOnly",
373
- }, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS[name].name + "ModelValidator", ropid_gtfs_1.RopidGTFS[name].outputMongooseSchemaObject));
381
+ if (!ropid_gtfs_1.RopidGTFS[name].name) {
382
+ throw new Error("Model name not found.");
374
383
  }
375
- return null;
384
+ return new models_1.PostgresModel(ropid_gtfs_1.RopidGTFS[name].name + "Model", {
385
+ hasTmpTable: true,
386
+ outputSequelizeAttributes: ropid_gtfs_1.RopidGTFS[name].outputSequelizeAttributes,
387
+ pgTableName: ropid_gtfs_1.RopidGTFS[name].pgTableName,
388
+ savingType: "insertOnly",
389
+ }, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS[name].name + "ModelValidator", ropid_gtfs_1.RopidGTFS[name].outputMongooseSchemaObject));
376
390
  };
377
- this.dataSource = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.name + "DataSource", new datasources_1.FTPProtocolStrategy({
378
- filename: config_1.config.datasources.RopidGTFSFilename,
379
- targetType: datasources_1.FTPTargetType.COMPRESSED,
380
- path: config_1.config.datasources.RopidGTFSPath,
381
- url: config_1.config.datasources.RopidFTP,
382
- whitelistedFiles: [
383
- "agency.txt",
384
- "calendar.txt",
385
- "calendar_dates.txt",
386
- "shapes.txt",
387
- "stop_times.txt",
388
- "stops.txt",
389
- "routes.txt",
390
- "trips.txt",
391
- ],
392
- encoding: "utf8",
393
- }), new datasources_1.JSONDataTypeStrategy({ resultsPath: "" }), null);
394
- this.transformation = new _1.RopidGTFSTransformation();
391
+ // Redis Models
395
392
  this.redisModel = new models_1.RedisModel(ropid_gtfs_1.RopidGTFS.name + "Model", {
396
393
  isKeyConstructedFromData: false,
397
394
  prefix: "files:ropid",
@@ -400,51 +397,14 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
400
397
  isKeyConstructedFromData: false,
401
398
  prefix: vehicle_positions_1.VehiclePositions.runs_trips.namespacePrefix,
402
399
  });
403
- this.metaModel = new _1.RopidGTFSMetadataModel();
404
- const cisStopsTypeStrategy = new datasources_1.JSONDataTypeStrategy({ resultsPath: "stopGroups" });
405
- cisStopsTypeStrategy.setFilter((item) => item.cis !== 0);
406
- this.dataSourceCisStops = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.name + "CisStops", new datasources_1.FTPProtocolStrategy({
407
- filename: config_1.config.datasources.RopidGTFSCisStopsFilename,
408
- path: config_1.config.datasources.RopidGTFSCisStopsPath,
409
- url: config_1.config.datasources.RopidFTP,
410
- encoding: "utf8",
411
- }), cisStopsTypeStrategy, null);
412
- this.transformationCisStops = new _1.RopidGTFSCisStopsTransformation();
413
- this.cisStopGroupsModel = new models_1.PostgresModel(ropid_gtfs_1.RopidGTFS.cis_stop_groups.name + "Model", {
414
- hasTmpTable: true,
415
- outputSequelizeAttributes: ropid_gtfs_1.RopidGTFS.cis_stop_groups.outputSequelizeAttributes,
416
- pgTableName: ropid_gtfs_1.RopidGTFS.cis_stop_groups.pgTableName,
417
- savingType: "insertOnly",
418
- }, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS.cis_stop_groups.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.cis_stop_groups.outputMongooseSchemaObject));
419
- this.cisStopsModel = new models_1.PostgresModel(ropid_gtfs_1.RopidGTFS.cis_stops.name + "Model", {
420
- hasTmpTable: true,
421
- outputSequelizeAttributes: ropid_gtfs_1.RopidGTFS.cis_stops.outputSequelizeAttributes,
422
- pgTableName: ropid_gtfs_1.RopidGTFS.cis_stops.pgTableName,
423
- savingType: "insertOnly",
424
- }, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS.cis_stops.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.cis_stops.outputMongooseSchemaObject));
425
400
  this.delayComputationTripsModel = new models_1.RedisModel(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "Model", {
426
401
  decodeDataAfterGet: JSON.parse,
427
402
  encodeDataBeforeSave: JSON.stringify,
428
403
  isKeyConstructedFromData: true,
429
404
  prefix: ropid_gtfs_1.RopidGTFS.delayComputationTrips.mongoCollectionName,
430
405
  }, new golemio_validator_1.Validator(ropid_gtfs_1.RopidGTFS.delayComputationTrips.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.delayComputationTrips.outputMongooseSchemaObject));
431
- // Ropid GTFS Run Numbers
432
- this.dataSourceRunNumbers = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.runNumbers.name + "DataSource", new datasources_1.FTPProtocolStrategy({
433
- filename: config_1.config.datasources.RopidGTFSRunNumbersFilename,
434
- path: config_1.config.datasources.RopidGTFSRunNumbersPath,
435
- url: config_1.config.datasources.RopidFTP,
436
- encoding: "utf8",
437
- }), new datasources_1.CSVDataTypeStrategy({
438
- fastcsvParams: { delimiter: ",", headers: true },
439
- subscribe: (json) => json,
440
- }), new golemio_validator_1.JSONSchemaValidator(ropid_gtfs_1.RopidGTFS.runNumbers.name + "DataSource", ropid_gtfs_1.RopidGTFS.runNumbers.datasourceJsonSchema));
441
- this.transformationRunNumbers = new _1.RopidGTFSRunNumbersTransformation();
442
- this.runNumbersModel = new models_1.PostgresModel(ropid_gtfs_1.RopidGTFS.runNumbers.name + "Model", {
443
- hasTmpTable: true,
444
- outputSequelizeAttributes: ropid_gtfs_1.RopidGTFS.runNumbers.outputSequelizeAttributes,
445
- pgTableName: ropid_gtfs_1.RopidGTFS.runNumbers.pgTableName,
446
- savingType: "insertOnly",
447
- }, new golemio_validator_1.JSONSchemaValidator(ropid_gtfs_1.RopidGTFS.runNumbers.name + "ModelValidator", ropid_gtfs_1.RopidGTFS.runNumbers.outputJsonSchema));
406
+ // MetaData Model
407
+ this.metaModel = new _1.RopidGTFSMetadataModel();
448
408
  // Ropid Departures Presets
449
409
  this.dataSourceDeparturesPresets = new datasources_1.DataSource(ropid_departures_presets_1.RopidDeparturesPresets.name + "DataSource", new datasources_1.FTPProtocolStrategy({
450
410
  filename: config_1.config.datasources.RopidDeparturesPresetsFilename,
@@ -459,6 +419,77 @@ class RopidGTFSWorker extends workers_1.BaseWorker {
459
419
  pgTableName: ropid_departures_presets_1.RopidDeparturesPresets.pgTableName,
460
420
  savingType: "insertOnly",
461
421
  }, new golemio_validator_1.JSONSchemaValidator(ropid_departures_presets_1.RopidDeparturesPresets.name + "ModelValidator", ropid_departures_presets_1.RopidDeparturesPresets.outputJsonSchema));
422
+ /** Ropid GTFS Dataset Map Dependencies **/
423
+ // Ropid GTFS
424
+ this.dataSourceGtfs = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.name + "DataSource", new datasources_1.FTPProtocolStrategy({
425
+ filename: config_1.config.datasources.RopidGTFSFilename,
426
+ targetType: datasources_1.FTPTargetType.COMPRESSED,
427
+ path: config_1.config.datasources.RopidGTFSPath,
428
+ url: config_1.config.datasources.RopidFTP,
429
+ whitelistedFiles: [
430
+ "agency.txt",
431
+ "calendar.txt",
432
+ "calendar_dates.txt",
433
+ "shapes.txt",
434
+ "stop_times.txt",
435
+ "stops.txt",
436
+ "routes.txt",
437
+ "trips.txt",
438
+ ],
439
+ encoding: "utf8",
440
+ }), new datasources_1.JSONDataTypeStrategy({ resultsPath: "" }), null);
441
+ this.transformationGtfs = new _1.RopidGTFSTransformation();
442
+ // Ropid GTFS Run Numbers Datasource
443
+ this.dataSourceRunNumbers = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.run_numbers.name + "DataSource", new datasources_1.FTPProtocolStrategy({
444
+ filename: config_1.config.datasources.RopidGTFSRunNumbersFilename,
445
+ path: config_1.config.datasources.RopidGTFSRunNumbersPath,
446
+ url: config_1.config.datasources.RopidFTP,
447
+ encoding: "utf8",
448
+ }), new datasources_1.CSVDataTypeStrategy({
449
+ fastcsvParams: { delimiter: ",", headers: true },
450
+ subscribe: (json) => json,
451
+ }), new golemio_validator_1.JSONSchemaValidator(ropid_gtfs_1.RopidGTFS.run_numbers.name + "DataSource", ropid_gtfs_1.RopidGTFS.run_numbers.datasourceJsonSchema));
452
+ this.transformationRunNumbers = new _1.RopidGTFSRunNumbersTransformation();
453
+ // Ropid GTFS CIS STOPS Datasource
454
+ const cisStopsTypeStrategy = new datasources_1.JSONDataTypeStrategy({ resultsPath: "stopGroups" });
455
+ cisStopsTypeStrategy.setFilter((item) => item.cis !== 0);
456
+ this.dataSourceCisStops = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.name + "CisStops", new datasources_1.FTPProtocolStrategy({
457
+ filename: config_1.config.datasources.RopidGTFSCisStopsFilename,
458
+ path: config_1.config.datasources.RopidGTFSCisStopsPath,
459
+ url: config_1.config.datasources.RopidFTP,
460
+ encoding: "utf8",
461
+ }), cisStopsTypeStrategy, null);
462
+ this.transformationCisStops = new _1.RopidGTFSCisStopsTransformation();
463
+ // Ropid GTFS Ois Datasource
464
+ this.dataSourceOisMapping = new datasources_1.DataSource(ropid_gtfs_1.RopidGTFS.name + "Ois", new datasources_1.FTPProtocolStrategy({
465
+ filename: config_1.config.datasources.RopidGTFSOisFilename,
466
+ path: config_1.config.datasources.RopidGTFSOisPath,
467
+ url: config_1.config.datasources.RopidFTP,
468
+ encoding: "utf8",
469
+ }), new datasources_1.JSONDataTypeStrategy({ resultsPath: "" }), new golemio_validator_1.JSONSchemaValidator(ropid_gtfs_1.RopidGTFS.ois.name + "DataSource", ropid_gtfs_1.RopidGTFS.ois.datasourceJsonSchema));
470
+ this.transformationOisMapping = new RopidGTFSOisTransformation_1.RopidGTFSOisMappingTransformation();
471
+ this.datasetMap = {
472
+ [_1.DatasetEnum.PID_GTFS]: {
473
+ datasource: this.dataSourceGtfs,
474
+ transformation: this.transformationGtfs,
475
+ cacheContentType: CacheContentType.CSV,
476
+ },
477
+ [_1.DatasetEnum.CIS_STOPS]: {
478
+ datasource: this.dataSourceCisStops,
479
+ transformation: this.transformationCisStops,
480
+ cacheContentType: CacheContentType.JSON,
481
+ },
482
+ [_1.DatasetEnum.OIS_MAPPING]: {
483
+ datasource: this.dataSourceOisMapping,
484
+ transformation: this.transformationOisMapping,
485
+ cacheContentType: CacheContentType.JSON,
486
+ },
487
+ [_1.DatasetEnum.RUN_NUMBERS]: {
488
+ datasource: this.dataSourceRunNumbers,
489
+ transformation: this.transformationRunNumbers,
490
+ cacheContentType: CacheContentType.JSON,
491
+ },
492
+ };
462
493
  this.queuePrefix = config_1.config.RABBIT_EXCHANGE_NAME + "." + ropid_gtfs_1.RopidGTFS.name.toLowerCase();
463
494
  }
464
495
  }