From 0cfb04bfed93d72f28c1048cfdccae9f8998f6ac Mon Sep 17 00:00:00 2001 From: Falk <falk.neumann@adfinis.com> Date: Thu, 11 Apr 2024 18:19:40 +0200 Subject: [PATCH] feat(street-service): add low level request optimization for multi language search --- addon/services/languages.js | 51 ++++++++++++ addon/services/street.js | 107 +++++++++++++++++--------- tests/unit/services/languages-test.js | 37 +++++++++ 3 files changed, 157 insertions(+), 38 deletions(-) create mode 100644 addon/services/languages.js create mode 100644 tests/unit/services/languages-test.js diff --git a/addon/services/languages.js b/addon/services/languages.js new file mode 100644 index 00000000..781b8764 --- /dev/null +++ b/addon/services/languages.js @@ -0,0 +1,51 @@ +import Service, { inject as service } from "@ember/service"; +import { languageOptions } from "ember-ebau-gwr/models/options"; + +export default class LanguagesService extends Service { + @service config; + + languages = { + AG: ["de"], + AR: ["de"], + AI: ["de"], + BL: ["de"], + BS: ["de"], + BE: ["de", "fr"], + FR: ["de", "fr"], + GE: ["de", "fr"], + GL: ["de"], + GR: ["de", "rm", "it"], + JU: ["fr"], + LU: ["de"], + NE: ["fr"], + NW: ["de"], + OW: ["de"], + SH: ["de"], + SZ: ["de"], + SO: ["de"], + SG: ["de"], + TI: ["it"], + TG: ["de"], + UR: ["de"], + VD: ["fr"], + VS: ["de", "fr"], + ZG: ["de"], + ZH: ["de"], + }; + + get availableLanguages() { + return this.config.cantonAbbreviation + ? this.languages[this.config.cantonAbbreviation] + : ["de", "rm", "fr", "it"]; + } + + codeToLanguage(code) { + return Object.entries(languageOptions).find( + ([, value]) => value === code, + )[0]; + } + + languageToCode(languageAbbreviation) { + return languageOptions[languageAbbreviation]; + } +} diff --git a/addon/services/street.js b/addon/services/street.js index a3583c62..4e6b2f8e 100644 --- a/addon/services/street.js +++ b/addon/services/street.js @@ -1,12 +1,21 @@ -import { languageOptions } from "ember-ebau-gwr/models/options"; +import { inject as service } from "@ember/service"; +import { task } from "ember-concurrency"; import Street, { StreetList } from "ember-ebau-gwr/models/street"; import GWRService from "./gwr"; export default class StreetService extends GWRService { + @service languages; + cacheKey = "ESID"; cacheClass = Street; - cachedLanguageOverride; + cachedLanguageOverrides; + + constructor(...args) { + super(...args); + + this.resetCachedLanguages(); + } async get(ESID) { if (!ESID) { @@ -18,54 +27,76 @@ export default class StreetService extends GWRService { return this.cache(street); } - get language() { - return languageOptions[this.intl.primaryLocale?.split("-")?.[0]]; + get primaryLanguage() { + return this.intl.primaryLocale?.split("-")?.[0]; } - async search(query = {}) { - if (this.cachedLanguageOverride) { - query.language = this.cachedLanguageOverride; - } + get language() { + return this.languages.languageToCode(this.primaryLanguage); + } - const searchResult = await super.search(query, query.EGID, { + @task + *_search(query) { + return yield super.search(query, query.EGID, { xmlMethod: "getStreet", urlPath: "streets", listModel: StreetList, listKey: "street", searchKey: "streetWithoutStreetGeometryType", }); + } - if (!searchResult) { - let results = []; - - for (const [lang, code] of Object.entries(languageOptions)) { - query.language = code; - - results.push({ - lang: [lang, code], - result: super.search(query, query.EGID, { - xmlMethod: "getStreet", - urlPath: "streets", - listModel: StreetList, - listKey: "street", - searchKey: "streetWithoutStreetGeometryType", - }), - }); - } - - results = await Promise.allSettled( - results.map(async ({ lang, result }) => { - return { lang, result: await result }; + resetCachedLanguages() { + this.cachedLanguageOverrides = new Set([]); + } + + async searchMultiple(query, useCachedLanguagesOnly) { + let results = []; + + for (const lang of useCachedLanguagesOnly + ? this.cachedLanguageOverrides + : this.languages.availableLanguages) { + const code = this.languages.languageToCode(lang); + query.language = code; + + results.push({ + lang: [lang, code], + result: this._search.perform(query, query.EGID, { + xmlMethod: "getStreet", + urlPath: "streets", + listModel: StreetList, + listKey: "street", + searchKey: "streetWithoutStreetGeometryType", }), - ); - return results - .filter(({ value }) => value.result?.length) - .reduce((previous, { value: { lang, result } }) => { - this.cachedLanguageOverride = lang[1]; - return previous.concat(result); - }, []); + }); } - return searchResult; + results = await Promise.allSettled( + results.map(async ({ lang, result }) => { + return { lang, result: await result }; + }), + ); + return results + .filter(({ value }) => value.result?.length) + .reduce((previous, { value: { lang, result } }) => { + this.cachedLanguageOverrides.add(lang[0]); + return previous.concat(result); + }, []); + } + + async search(query = {}) { + const lastQueryString = + this._search.lastPerformed?.args[0]?.description?.descriptionLong.replaceAll( + "*", + "", + ) || ""; + const currentQueryString = + query.description?.descriptionLong?.replaceAll("*", "") || ""; + + if (lastQueryString && currentQueryString.includes(lastQueryString)) { + return this.searchMultiple(query, true); + } + this.resetCachedLanguages(); + return this.searchMultiple(query); } } diff --git a/tests/unit/services/languages-test.js b/tests/unit/services/languages-test.js new file mode 100644 index 00000000..cc7871b2 --- /dev/null +++ b/tests/unit/services/languages-test.js @@ -0,0 +1,37 @@ +import { setupTest } from "dummy/tests/helpers"; +import { module, test } from "qunit"; + +module("Unit | Service | languages", function (hooks) { + setupTest(hooks); + + test("available languages for a given canton", function (assert) { + const configService = this.owner.lookup("service:config"); + const languagesService = this.owner.lookup("service:languages"); + + configService.cantonAbbreviation = "GR"; + + assert.deepEqual(languagesService.availableLanguages, ["de", "rm", "it"]); + + configService.cantonAbbreviation = "BE"; + + assert.deepEqual(languagesService.availableLanguages, ["de", "fr"]); + }); + + test("transforms language abbrevation to gwr API language code", function (assert) { + const service = this.owner.lookup("service:languages"); + + assert.strictEqual(service.languageToCode("de"), 9901); + assert.strictEqual(service.languageToCode("rm"), 9902); + assert.strictEqual(service.languageToCode("fr"), 9903); + assert.strictEqual(service.languageToCode("it"), 9904); + }); + + test("transforms gwr API language code to language abbrevation", function (assert) { + const service = this.owner.lookup("service:languages"); + + assert.strictEqual(service.codeToLanguage(9901), "de"); + assert.strictEqual(service.codeToLanguage(9902), "rm"); + assert.strictEqual(service.codeToLanguage(9903), "fr"); + assert.strictEqual(service.codeToLanguage(9904), "it"); + }); +});