ivpk / dsa

Duomenų struktūros aprašo specifikacija.
GNU Affero General Public License v3.0
0 stars 1 forks source link

Multiple sources for same model name #13

Open sirex opened 4 months ago

sirex commented 4 months ago

Nuo pradžių DSA buvo kuriamas, didesnį dėmesį skiriant SQL duomenų šaltiniams, kurie turi didesnį lankstumą ir užtenka aprašyti vieną modelį, ko užtenka generuojant visus API prieigos taškus (getone, getall, insert, ...).

Šiuo metu, DSA gali būti aprašytas tik vienas modelio pavadinimas, viename duomenų rinkinyje arba tiksliau vienoje vardų erdvėje ir modelio pavadinimai negali dubliuotis.

Kai duomenų šaltinis yra API paslauga, turime daugiau apribojimų ir atsiranda poreikis, vienam modeliui priskirti kelis API prieigos taškus. Dažniausiai pasitaikantis atvejis, kai API turi du prieigos taškus, gauti vienam objektui, ir objektų sąrašui. Pavyzdys:

Prieigos taškas, kuris grąžina miestų sąrašą:

/cities

Atskiras prieigos taškas, kuris grąžina duomenis apie vieną miestą:

/cities/42

Turime du skirtingus šaltinius, kuriuos reikėtu priskirti vienam modeliui.

Iki šiol, kaip apėjimas, buvo naudojamos vardų erdvės, pavyzdžiui:

model=cities/City       resource.source=/cities
model=cities/city/City  resource.source=/cities/{id}

Toks variantas veikia, tačiau atsiranda problema, kad modeliai visais atvejais, generuoja visus getone, getall, ... veiksmus, kas nėra optimalu, kadangi /cities geriausiai naudoti getall atveju, o /cities/{id} getone atveju.

Todėl yra poreikis, nurodyti ir kokiam veiksmui konkretus API prieigos tašas turi būti naudojamas.

Papildomai, būna keli API prieigos taškai, kurie grąžina rezultatą taikant tam tikrus filtrus. Tai taip pat reikėtu atspindėti DSA.

Vienas iš galimų sprendimų, model stulpelyje nurodyti ne tik modelio kodinį pavadinimą, tačiau taip pat pateikti veiksmą ir filtrus.

Pavyzdys:

resource model property type ref source prepare
City id
id integer
name@lt string
continent ref Continent
continent.code string
resource1 json https://example.com/cities
City/:getall id cities
id integer id
name@lt string name
resource2 json https://example.com/cities/{id}
param id path()
City/:getone id city
id integer id
name@lt string name
resource3 json https://example.com/cities?europe=1
City?continent.code="eu" id cities
id integer id
name@lt string name
continent ref Continent "eu"
continent.code string "eu"

Tokiu atveju, jei vykdoma UDTS /City užklausa, tada naudojamas City/:getall resursas. Jei naudojama /City/{uuid} užklausa, tada naudojama City/:getone ir pan.

Tai reikalautu tam tikros resurso atrankos, pagal užklausos veiksmą ir filtro parametrus. Iš įgyvendinimo perspektyvos, išlieka manifest.models[City], tačiau atsiranda manifest.models[City].resources[...], kuris turėtu skirtingus resursus, pagal /:getone, /:getall, ?continent.code="eu" ir pan raktus.

Nesu įsitikinęs, ar būtent tokią struktūrą naudoti, bet turėtu būti galimybė greitai surasti su modeliu susietą resursą, pagal veiksmą ir pagal filtro parametrus.

Pilnas ir dalinis modeliai

Pilnas modelis arba tiesiog modelis, yra tas, kuris neturi jokių parametrų ir aprašo pilną modelį, pavyzdyje aukščiau, tai būtų City.

Dalinis modelis yra tas, kuris aprašo dalį modelio, tarkime modelis su tam tikru veiksmu, arba su tam tikrais filtrais, tokie pavyzdžiai būtų City/:getall - įgyvendina tik getall veiksmą, City/:getone - įgyvendina tik getone veiksmą ir kiti.

Prie dalinio modelio nebūtina aprašyti laukų, kadangi jie yra aprašyti prie pilno modelio, pavyzdys:

resource model property type ref source prepare
City id
id integer id
name@lt string name
continent ref Continent
continent.code string
resource1 json https://example.com/cities
City?select(id,name) cities
resource2 json https://example.com/cities/{id}
param id path()
City/:getone city
resource3 json https://example.com/cities?europe=1
City?continent.code="eu" cities
continent.code "eu"

Šiame pavyzdyje id ir name prie dalinių modelių nėra aprašomi, kadangi jie jau aprašyti prie pilno modelio. Aprašomos tik tos savybės, kurios skiriasi nuo varianto pateikto prie pilno modelio.

Šaltinio atranka

UDTS užklausos apdorojimo metu, turėtu būti atrenkama labiausiai specifiška model eilutė, kuri turi šaltinį.

Tarkime, iš pavyzdžių aukščiau, specifiškumas būtų nustatomas tokia tvarka:

# Labiausiai specifiška
City/:getone
City/continent.code="eu"

# Mažiau specifiškai
City/continent.code

# Mažiausiai specifiška
City

Palaikomos funkcijos

Dalinis modelis įgyvendina visas savybes aprašytas prie pilno modelio, tačiau savybių sąrašas gali būti susiaurintas, jei nurodytas select(), pavyzdžiui:

City?select(id, name)

Nurodo, kad dalinis modelis turi tik id ir name savybes. Toks modelis turi būti atrenkamas automatiškai, jei prašoma tik tokių savybių.

Jei pilnas modelis nėra susietas su jokiu šaltiniu ir su šaltiniu yra susietas tik dalinis modelis, kuris turi select() apribojimą, tada, jei per UDTS API prašoma daugiau duomenų, nei nurodyta select() turi būti grąžinama 501 Not Implemented klaida. Pavyzdys:

/City

Šiuo atveju, prašoma visų laukų, tačiau turime tik dalinį modelį su select(), kuris turi ne visus, o tik dalį laukų, tokia užklausa grąžins 501 Not Implemented klaidą.

Analogiškai, toks pat veikimas ir su kitais užklausos parametrais, tokiais kaip sort(), prop=value, limit ir pan. Jei šaltinis to neįgyvendina, tada grąžinama 501 klaida.

Palaikomi filtrai

Daliniai modeliai, gali nurodyti statinius arba dinaminius filtrus.

Statinis filtras, yra toks, kuris nurodo, kad šaltinis grąžina tik duomenis taikant tam tikrą filtrą, kurio nėra galimybės keisti, tokiu atveju nurodomi tarkim continent.code="eu", kuris reiškia, kad šis šaltinis, grąžina duomenis, kurie atitinka tokį filtrą.

Jei UDTS API klientas būtent pateikia tokį filtrą, turėtu būti parenkamas būtent šis dalinis modelis.

Dinaminis filtras, yra toks filtras, kurio reikšmes galima nurodyti šaltiniui, tokiu atveju, filtrai nurodomi, nepateikiant jokios reikšmės continent.code, kadangi reikšmė nenurodyta, tai reiškia, kad filtras yra dinaminis.

Pavyzdys:

City?id&name&name.gt()&continent.code

Nurodoma, kad šaltinis palaiko filtrus pagal tris laukus iš kurių name palaiko dvi operacijas eq ir gt. Jei pateiktas tik lauko pavadinimas, daroma, prielaida, kad palaikomas eq filtras su šia savybe.

Transformacija

getone

getone atveju, per UDTS gauname UUID, kuris yra išorinis globalus identifikatorius.

Lokalus identifikatorius nustatomas pagal pirminį raktą arba pagal prepare stulpelyje pateiktą getone(key) funkciją, kuri pirmuoju argumentu, nurodo lokalaus identifikatoriaus pavadinimą.

Naudojant keymap, pagal globalų identifikatorių, gaunamas lokalus ir į šaltinį kreipiamasi su lokaliu identifikatoriumi.

Filtrai

Filtrų atveju, per UDTS gauname filtrų reikšmes, naudojant loginio modelio pavadinimus.

Naudodami parametrų sąsają su savybėmis, nustatome, kaip parametrai vadinami šaltinyje ir kaip turėtu būti perduodamos reikšmės šaltiniui.

Žiūrėti:

Priklauso nuo

Related