Open CodoDerDritte opened 1 year ago
Tämä näyttäisi ainakin äkkipäätä toimivan hyvin eikä synnytä viiveitäkään:
begin;
select item_barcode_nextval from sequences for update;
update sequences set item_barcode_nextval=item_barcode_nextval+1;
commit;
Query OK, 1 row affected (0.000 sec)
Rows matched: 1 Changed: 1 Warnings: 0
Query OK, 0 rows affected (0.002 sec)
Yksi tapa hoitaa viivakoodien generointi voisi olla käyttää unix+timestamppia + sadasosasekunteja. Silloin tietokannan kanssa ei tarvitsisi generointivaiheessa tehdä mitään, vaan generointi hoidettaisiin työasemapäässä.
Ainakin SELECT ... FOR UPDATE ei tule toimimaan Kohan päässä. Kohan viivakoodien generointi on koodattu törpösti ja sequences-taulusta haetut item_barcode_nextval arvot hyppäävät useamman arvon yli, jos niteitä yritetään lisätä useampi kerralla. Tästä voi seurata arvojen loppuminen kesken ja tuplien syntyminen, jolloin prefixiä jouduttaisiin muuttamaan.
Kokeillaan tuota unix+timestamp+sadasosasekuntti muotoa seuraavaksi.
Pääkäyttäjäpalaveri 20.9.2023:
Koha-Suomen palaveri 25.9.2023:
Tehdään muutos ensin testeille ja siinä yhteydessä on hyvä testata laajasti, minkälaisia viivakoodeja tulostuu tarroille ja miten automaatit ja lukijat lukevat niitä.
Koha-Suomen palaveri 25.9.2023:
1. viivakoodista tulee saman mittainen kuin varaustunnus (12 merkkiä) + prefiksi. 2. koskee kaikkia viivakoodeja (myös editx).
Tehdään muutos ensin testeille ja siinä yhteydessä on hyvä testata laajasti, minkälaisia viivakoodeja tulostuu tarroille ja miten automaatit ja lukijat lukevat niitä.
Tarkennan hieman tuota 1. kohtaa, viivakoodin pituus olisi 14 merkkiä + prefiksi. Näin siis jos käytetään koko timestampia, yyyymmddHHMMSS.
Meillä tuli tähän liittyen mieleen sellainen ehdotus, että timestampiin otettaisiin mukaan sadasosasekunnit päällekkäisten viivakoodien minimoimiseksi, ja timestampin vuosiluku karsittaisiin kahteen merkkiin jottei viivakoodin pituus kasvaisi enempää. Eli timestamp olisi jotain tällaista: yymmddHHMMSSSS. Kuulostaisiko tällainen ehdotus järkevältä?
Meillä tuli tähän liittyen mieleen sellainen ehdotus, että timestampiin otettaisiin mukaan sadasosasekunnit päällekkäisten viivakoodien minimoimiseksi, ja timestampin vuosiluku karsittaisiin kahteen merkkiin jottei viivakoodin pituus kasvaisi enempää. Eli timestamp olisi jotain tällaista: yymmddHHMMSSSS. Kuulostaisiko tällainen ehdotus järkevältä?
Tää ei välttämättä ole yhtään huono idea, koska törmäsin alkuperäisen toteutuksen kanssa ongelmiin. Vaikka viivakoodin lopussa käytetään sekuntteja, niin muistaakseni hankinnan puolella Koha ampuu useamman niteen sellaisella tahdilla ulos, että tulee tuplia. Pitää kokeilla noita sadasosasekuntteja vielä.
Testailin tätä myös noiden millisekunttien osalta joulukuun puolella ja vaikutti sille, ettei generointi ilman kannan tarkistamista tuplien varalta tule onnistumaan silläkään tavalla. Tää Kohan tapa käsitellä viivakoodeja rakennettu niin, että se käyttäytyy hieman eri tavalla riippuen siitä, mitä kautta nide lisätään ja kuinka monta niitä lisätään. Isoin ongelma tässä on hankinta ja se, että kun sen kautta lisätään useampi nide niin näille generoidaan aina sama viivakoodi. Näin käy myös jos viivakoodi koostuu timestampista jossa on mukana millisekunnit. Niteen lisäämisessä suoraan tietueeseen tai kausijulkaisuun ei ole samaa ongelmaa, koska ne toimii hieman eri tavalla. Mutta ei näissäkään voi mennä minusta täysin takuuseen siitä, etteikö tuplia pääsisi syntymään, jos joku lisää tietuetta juuri samaan aikaan hankinnan kautta.
Tässä on siis nyt sellainen tilanne, että viivakoodien generointi timestampin kanssa ei tuo minun nähdäkseni mitään lisäarvoa meille, koska kantaa pitää joka tapauksessa tarkistella tuplien varalta ainakin hankinnan osalta. Ja siitähän tällä juuri haluttiin eroon.
Testeille on tehty parannuksia viivakoodien generointiin, nyt viivakoodi tulee sekunnin tarkkuudella ja lopussa on vielä juokseva numero. Koha haluaa hyvin vahvasti käyttää tuota juoksevaa numeroa, joten siitä ei päässyt eroon. Tässä nyt täytyy todeta, että täysin aukottomaksi tuota ei saa ja mahdollista on, että joskus saattaa tulla kaksi viivakoodin samalla sekunnilla ja juoksevalla numerolla.
Testasin viivakoodin generoimista niteen lisäyksessä (sekä yksittäisen että kerralla useamman kopion lisäämistä) ja kausijulkaisujen vastaanotossa, sekä lisäsin vielä hankinnan kautta uuden tilatun niteen. Kaikissa tapauksissa muodostui viivakoodi sekunnin tarkkuudella + lopussa juokseva numero.
Tästä on jo tiketissä aiemminkin puhuttu, mutta varmuuden vuoksi hoksautan vielä että muutos kasvattaa viivakoodin pituutta ja esim. Vaskissa nykyisellä prefiksillä viivakoodista tulee pidempi mitä meillä automaattien asetuksissa on sallittu. Ollaankin mietitty, että lyhennettäisiin prefiksiä, jos tämä muutos toteutuu, niin sitten viivakoodin pituus ei kasvaisi eikä tarvitsisi miettiä automaattien viivakoodiasetusten säätämistä.
Testasimme neljän käyttäjän voimin viivakoodin samanaikaista luomista (Vaski-testillä). Testauksessa saimme neljä samaa viivakoodia, eli aukottomaksi generointia ei tosiaan saa. Ratkaisu vähentää kuitenkin päällekäisyyksiä.
Testasin viivakoodin generointia Kirkes-testillä tekemällä niteen lisäyksen ja kausijulkaisujen vastaanoton suunnilleen samanaikaisesti, ja niihin muodostui oikeanlaiset viivakoodit sekunnin tarkkuudella + juoksevalla numerolla. Tuota Susannan yllä mainitsemaa täsmälleen samalla sekunnilla aloittamista en nyt pääse testaamaan kenenkään kanssa.
Kehitysehdotukseni
Nidettä lisättäessä ja EDItX sanomia käsiteltäessä uuden niteen viivakoodin pitäisi tulla sequences-taulun item_barcode_nextval -kentästä. Arvon noutamisen taulusta tulisi toimia siten että arvolle tehdään samanaikaisesti update ja select, jotta samaa viivakoodiarvoa ei tarjota useammalle niteitä lisäävälle käyttäjälle tai EDItX order processorille.
Jotain muuta?
Samanaikaisuuden toteuttamiseen on ainakin viisi tapaa, näiden keskinäinen toimivuus/järkevyys/paremmuus täytyy selvittää:
1) Select + update transaktiona. Tämä voi aiheuttaa sequences-tauluun kohdistuviin kyselyihin ja updateihin pientä viiveilyä, mutta puhuttanee kuitenkin todennäköisesti reilusti alle sekunnin pituisista ajoista, joten onko käytännön kannalta ongelma?
2) Eksplisiittinen table lock koodissa. Eli lukitaan arvon kyselyn + päivityksen ajaksi sequences taulu (sekä read että write). Jälleen voi olla suorituskyvyn kannalta hankala, mutta onko sittenkään käytännössä. Jonojen pitäisi joka tapauksessa purkautua siististi (kai).
3) Select ... for update. Periaatteessa toisella tapaa toteutettu transaktio, mutta tämän käytöllä voisi olla positiivinen vaikutus suorituskykyyn, jos transaktion käyttö muuten osoittautuisi ongelmalliseksi.
Jos transaktion käyttö osoittautuu mahdottomaksi, voidaan homma toteuttaa suoraan tietokannassa:
4) Update on select triggeri, joka päivittää barcode_max_value arvon (+1) aina kun arvolle tehdään select. Lieveilmiönä arvo kasvaa myös esimerkiksi jos tietokannassa ajaa select * from sequences, joka voi kyllä olla ongelma.
5) Output clause, josta nyt en ole ihan varma että mitä se tekee, mutta ilmeisesti jotain järkevän suuntaista silloin kun on tarpeen tehdä esimerkiksi select ja update "samanaikaisesti", kuten tarve meillä tässä nyt on.