Re: [TYPO3-german] Caching von Webserviceantworten
Hallo Fabian. > Ok, soweit verstanden. Wenn ich das richtig sehe, werden hier aber auch nur > dann Daten angezeigt, wenn der Scheduler gelaufen ist. Bei neu eingefügten > Plugins hab ich potentiell fast 1 Stunde keine Daten, die ich ausgeben kann. Nein, falsch verstanden. Der Scheduler synchronisiert nicht die Daten die die Plugins brauchen sondern alle die er bekommt. Dem Scheduler soll vollkommen egal sein welche Daten die Plugins brauchen. Man kann das ggf. optimieren und diejenigen Daten weglassen die unter keinen Umständen von Plugins angezeigt werden können. Wenn sich z.B. das Plugin ohnehin immer auf das aktuelle Jahr bezieht und im Plugin auch kein Zeitwähler existiert der Daten älter als ein Jahr beschreibt, dann kann man den Scheduler natürlich so optimieren, dass er nur das aktuelle Jahr in die Datenbank legt. Aber abgesehen von solchen kleinen Optimierungen soll der Scheduler wirklich alles synchronisieren was über die API kommt, weil er nicht wissen kann, welche Daten die Plugins brauchen. > Hast du dazu noch ein Beispiel bzw. Anhaltspunkt? Aus welchem Grund würdest > du den DataHandler > (https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Typo3CoreEngine/Database/Index.html > ?) vorziehen? Du hast bei der Synchronisation praktisch keinerlei Vorteile, das Domain-Model zu verwenden. Wenn die Quelldaten XML sind, wirst Du das wohl per PHP DOMDocument oder SimpleXML einlesen, dann per xpath die Objekte ansprechen und darüber iterieren. Pro Result des xpath-Query machst Du dann ein „new“ eines Extbase-Models und schreibst 50 Zeilen Code, nur im alle Attribute aus dem SimpleXML-Element in das Extbase-Model zu überführen. Anschließend kommt das nach „repository->add()“ und die Daten gehen in die Datenbank. Die im Frontend relevanten Vorteile des ORM verwendet der Import in dieser Form gar nicht. Weder brauchst Du das Query-Model, weil Du ja gar keine Daten aus dem Repository ausliest. Bestenfalls musst Du wissen ob es das Objekt schon gibt. Das machst Du aber nicht über „findByIdentifier()“ sondern vielmehr liest Du am Anfang des Import-Prozesses per „findAll()“ alle bestehenden Objekte aus und hältst sie im Arbeitsspeicher vor. Das QOM kommt also nicht zum Zug weil „findAll()“ ohnehin nur ein „SELECT * FROM table“ macht, ohne weiter Einschränkung. Noch brauchst Du den Property Mapper, weil Deine Quelldaten gar nich in der Struktur vorliegen die der Property Mapper direkt verwenden kann. Noch helfen Dir Relationen, insbesondere mit Lazy Loading, weil Du Die ja zur Laufzeit erst aufbaust und dann nichts lazy geladen werden kann. Auch das Mapping der Daten zwischen „so wie ich mir das im Objekt vorstelle“ zu „so wie das in die Datenbank muss“ fehlt komplett, weil die Daten aus dem XML großteils nicht in dem Format vorliegen wie sie im Objekt sein sollen. Beispiel: Datum. Im XML wird das wohl als Timestamp oder als RFC-Format vorliegen, also als String. Das Extbase Domain-Objekt soll natürlich ein DateTime-Objekt verwenden. Dein Import also muss, wenn Du Extbase verwendest, erst per „new Date($xmlValue)“ ein neues DateTime-Objekt erzeugen das Du dann an Dein Model übergeben kannst. Das ist Deine Aufgabe im ImportCommand. Oder in der Factory, wenn Du das in eine Serviceklasse auslagern möchtest. Nur, damit im unmittelbar nachfolgenden Schritt Extbase wieder dieses Date-Objekt zum String oder Integer konvertieren kann damit es in die Datenbank passt. Zwar findet das Mapping da also offensichtlich durchaus statt, es nimmt Dir aber keine Arbeit ab. Dann kannst Du auch gleich auf den ORM verzichten und die Daten per DataHandler in die Datenbank schieben. Immerhin spart das dann wenigstens noch ein paar MB Arbeitsspeicher. Und nicht zuletzt erzeugt der DataHandler eine sinnvolle History. Du kannst also als Administrator jederzeit im Backend die History eines konkreten Datensatzes ansehen und nachvollziehen, wann die SOAP-API welchen Wert verändert hat. Du glaubst gar nicht, wie häufig ich mit Kunden telefonieren muss und ihnen erklären, dass die Daten die ihre Webseite anzeigt schon richtig sind und dass das Quellsystem (Youtube, Vimeo, irgend ein RSS feed für News, oder ein hausgemachtes Protokoll zur Veröffentlichung von Stellenausschreibungen) die Daten bereits falsch liefert. Wenn ich dann belegen kann, dass die Daten da schon seit vier Tagen falsch sind, und zwar um exakt 13:35 falsch synchronisiert wurden, finden Kunden in der Regel inhouse den Schuldigen Kollegen, der die Daten im Quellsystem zum fraglichen Zeitpunkt geändert hat. Beste Grüße, Stephan Schuler Web-Entwickler | netlogix Web Solutions Telefon: +49 (911) 539909 - 0 E-Mail: stephan.schu...@netlogix.de Web: websolutions.netlogix.de Neu: Wir sind Amazon Web Services Partner. Mehr erfahren: https://websolutions.netlogix.de/technologie/amazon-web-services-aws netlogix GmbH & Co. KG IT-Services |
Re: [TYPO3-german] Caching von Webserviceantworten
Alles klar, jetzt habe ich das "Problem" mit dem Caching-Framework verstanden. Mein Vorschlag bezieht sich *nicht* auf das CF. Bau ein Extbase Domain Model mit Domain-Objekten, sinnvollem Datenbank-Layout für Dein Model und einem Repository, das Du im Plugin entsprechend Deinen Anforderungen fragen kannst. Der Scheduler füllt die Datenbank asynchron. Ich würde den Scheduler nicht über Extbase sondern über den DataHandler mit der Datenbank reden lassen, aber das ist Implementierungsdetail. Diese Daten siehst Du dann auch im TYPO3 Backend. Wenn Du möchtest, dass Deine Redakteure sie nicht bearbeiten können, verweiger ihnen entsprechende Berechtigungen. Ok, soweit verstanden. Wenn ich das richtig sehe, werden hier aber auch nur dann Daten angezeigt wenn der Scheduler gelaufen ist. Bei neu eingefügten Plugins hab ich potentiell fast 1 Stunde keine Daten, die ich ausgeben kann. Lässt sich das irgendwie vermeiden? Durch den erwähnten Hook z.B.? Wenn der Webservice aus irgendwelchen Gründen zu der Zeit keine Daten liefert, dann kann man ja immer noch auf den nächsten Scheduler Durchlauf warten und dem Redakteur eine entsprechende Notitz anzeigen. Der Scheduler füllt die Datenbank asynchron. Hast du dazu noch ein Beispiel bzw. Anhaltspunkt? Aus welchem Grund würdest du den DataHandler (https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/Typo3CoreEngine/Database/Index.html ?) vorziehen? Vielen Dank und viele Grüße Fabian ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo Fabian. So funktioniert das Caching-Framework nicht. Erstens machst Du einen Großteil dessen was das CF für Dich tun soll selbst und zweitens läufst Du Gefahr, irgendwann für eine gewisse Zeit keine Daten zu haben. https://docs.typo3.org/typo3cms/CoreApiReference/ApiOverview/CachingFramework/FrontendsBackends/Index.html Du willst primär FrontendInterface::has(), FrontendInterface::get() und FrontendInterface::remove() aufrufen. Jeweils ist Dein Cache-Content ein Array aus allen Objekten die für ein Plugin relevant sind. Der Cache im CF hat eine Lifetime. Wenn der Scheduler nicht rechtzeitig läuft – sagen wir, weil der SOAP-Server hängt, PHP in ein Timeout läuft und die Daten eben einfach nicht gespeichert werden – ist der Cache-Inhalt weg und Dein Plugin fliegt auf die Nase. Die einzige Möglichkeit die Du hast: Die Lifetime so hoch zu setzen, dass das nicht passiert. Dann hast Du das Lifetime-Feature ausgehebelt und baust es im Prinzip durch den Scheduler nach. Der zweite Punkt: Du hast doppelte Daten. Wenn Du zwei Plugins mit unterschiedlicher Konfiguration hast, bekommen Die nach Deiner Vorstellung unterschiedliche Cache-Identifier. Wenn sich die Daten dieser beiden Plugins überschneiden, hast Du die Objekte in beiden Caches unabhängig voneinander. Wenn Du es jetzt durch einen laggy SOAP-Server o.ä. schaffst, dass der Scheduler-Run für das eine Plugin klappt aber der für das zweite abbricht, zeigt Deine Seite vielleicht in den beiden Plugins unterschiedliche Informationen für das gleiche SOAP-Objekt an. Dann kommt der Flush. Es erfordert sehr viel Disziplin, wirklich nie und unter keinen Umständen ein „Clear all caches“ durchzuführen. Dass der Button aus dem rechten oberen Backend-Bereich verschwunden ist hat da schon sehr geholfen. Trotzdem sehe ich immer noch „Admin-Redakteure“, die jetzt übers Install-Tool „Clear all Caches“ drücken, wenn im Frontend mal was hängt. Bei mir passiert das „Clear all Caches“ immer, wenn ich einen neuen Code-Stand deploye. Je nach Projekt zwischen einmal die Woche und mehrmals täglich. Lässt sich nicht ändern, wenn neuer PHP-Code kommt sind Caches tödlich. Und was passiert, wenn man „Clear all Caches“ drückt? Natürlich wird das CF geleert. Dein Frontend hat erst mal keine Daten und darf auf den nächsten Scheduler-Run warten, im schlimmsten Fall dauert es dann eine Stunde, bis die Tabellen im Frontend wieder Daten bekommen. Du möchtest lokale Datenhaltung im CF simulieren. Das CF ist aber keinesfalls für lokale Datenhaltung gedacht. Leg ins CF nur solche Daten, die Du wirklich zu jeder Zeit rekonstruieren kannst. Und gestalte Deinen eigenen PHP-Code so, dass nichts davon abhängt, dass die Daten im CF liegen. Wenn Du willst, bau Dir ein Service-Objekt das Du „ServiceObject::getDataByConfig($config)“ fragst. Dieser Aufruf darf die Daten aus dem CF nehmen wenn sie drin sind, wenn nicht muss er sie vom SOAP-Server holen, ins CF legen und dann zurückgeben. Für den Aufrufer dieser Methode muss vollkommen transparent sein, ob der Service die Daten aus dem Cache hat oder live abgeholt hat. Nur so lässt sich das CF verwenden ohne dass Du früher oder später auf Probleme stößt. Genau das ist dann die Stelle, die das Frontend blockiert, wenn der SOAP-Server lahm ist. Mein Vorschlag bezieht sich *nicht* auf das CF. Bau ein Extbase Domain Model mit Domain-Objekten, sinnvollem Datenbank-Layout für Dein Model und einem Repository, das Du im Plugin entsprechend Deinen Anforderungen fragen kannst. Der Scheduler füllt die Datenbank asynchron. Ich würde den Scheduler nicht über Extbase sondern über den DataHandler mit der Datenbank reden lassen, aber das ist Implementierungsdetail. Diese Daten siehst Du dann auch im TYPO3 Backend. Wenn Du möchtest, dass Deine Redakteure sie nicht bearbeiten können, verweiger ihnen entsprechende Berechtigungen. Sicherlich gibt es auch in dieser Ausprägung noch den ein oder anderen Anwendungsfall für das CF, aber bitte ausschließlich im Frontend und nicht, wenn es um die Synchronisation der Daten zwischen SOAP-Request und TYPO3-Datenbank geht. Beste Grüße, Stephan Schuler Web-Entwickler | netlogix Web Solutions Telefon: +49 (911) 539909 - 0 E-Mail: stephan.schu...@netlogix.de Web: websolutions.netlogix.de Neu: Wir sind Amazon Web Services Partner. Mehr erfahren: https://websolutions.netlogix.de/technologie/amazon-web-services-aws netlogix GmbH & Co. KG IT-Services | IT-Training | Web Solutions Neuwieder Straße 10 | 90411 Nürnberg Telefon: +49 (911) 539909 - 0 | Fax: +49 (911) 539909 - 99 E-Mail: i...@netlogix.de | Web: http://www.netlogix.de netlogix GmbH & Co. KG ist eingetragen am Amtsgericht Nürnberg (HRA 13338) Persönlich haftende Gesellschafterin: netlogix Verwaltungs GmbH (HRB 20634) Umsatzsteuer-Identifikationsnummer: DE 233472254 Geschäftsführer: Matthias Schmidt ___
Re: [TYPO3-german] Caching von Webserviceantworten
Guten Morgen Stephan, vielen Dank, dass du dir die Zeit für die ausführlichen Antworten nimmst. Ich verstehe deine aufgeführten Punkte (denke ich zumindest), ich konnte mir allerdings noch kein "Gesamtbild" daraus bilden. Derzeit habe ich sowas im Kopf: - Plugin wird auf einer Seite eingefügt, konfiguriert und gespeichert. - Ein Hook holt beim Speichern (vorausgesetzt so einen Hook gibt es, bin noch am Infos suchen) initial die Daten vom Webservice und speichert diese mittels Caching Framework in den Cache (cf_irgendwas). Die Konfigurationsparameter des Plugins werden dabei als Identifier genutzt. - Bei Aufruf der Seite durch einen Nutzer holt der Controller die Daten aus der Cache Tabelle und gibt sie an das Fluid Template. - Scheduler läuft jede Stunde und geht die gecachten Einträge in cf_irgendwas durch. Ist der Ablaufzeitpunkt überschritten werden die Daten erneut abgefragt und der alte Datensatz im Cache gelöscht. Grüße Fabian ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo Fabian. > Aber wie mache ich es dann? Ich muss ja irgendwie aus der XML-Antwort meine > Objekte basteln, über die ich dann im Fluid Template iteriere und die > Tabellen zusammensetze. Das ist genau der Punkt. Du wirst also erst in einem „findAll()“ alle Objekte aus der Datenbank holen. Dann lässt Du Dir über den SOAP-Request alle XMLe geben. Jetzt kannst Du in einer geschachtelten Schleife über beide drüber iterieren und prüfen welche zu aktualisieren sind, welche neu zu erstellen und welche zu löschen. Das kostet Dich natürlich erstens ganz massiv RAM. Und zweitens musst Du das reine Synchronisations-Hilfsmittel „tstamp“ als Property Deines Models mappen – obwohl der tstamp überhaupt nichts mit Deiner Domäne zu tun hat. Der gehört da also schlicht nicht hin. Du bläst damit Deine Domäne also mit „Kram“ auf. Dann kommt alles mit Repository->add(), Repository->update() oder Repository->delete() in die Datenbank, und unter Umständen musst Du dann ein „persistAll()“ aufrufen damit ein anschließender Filter-Query auch wirklich die aktualisierten Daten aus der Datenbank bekommt. Ohne das persistAll() werden die Persistenzoperationen durchgeführt, *nachdem* die Action erfolgreich durchlaufen wurde. Ein „findByIrgendwas()“ innerhalb der Action wenn in den ersten Zeilen der Action neue Daten in die Datenbank gekommen sind wird diese neuen Daten sonst nicht finden. Wenn Du jetzt noch „updateoptimiert“ z.B. ein Plugin hast das nur die Daten von 2017 haben möchte, ein weiteres Plugin das nur die Daten einer bestimmten Kategorie aber dafür zeitunabhängig haben möchte und ein drittes Plugin das alle Daten sortiert nach Titel dafür mit Pagination anzeigen soll. Dann tust Du Dir schon schwer, wirklich sinnvoll auf Basis einer solchen Teilmenge zu ermitteln, welche deiner lokalen Daten gelöscht werden sollen oder welche neu sind. Das heißt Du musst für jede Plugin-Filter-Teilmenge sowohl den Extbase-Query als auch die SOAP-Anfrage so hin optimieren, dass sie die exakt identischen Werte liefern. Andernfalls legst Du Daten an die es schon gibt (wenn sie von Deinem Extbse-Query ausgefiltert wurden aber über SOAP kommen) oder löchst Daten die Du eigentlich noch brauchst (wenn der Extbase-Query zu lasch war und mehr Datenliefert als Du anzeigen möchtest). Sobald Du jetzt die Logik was eigentlich wirklich angezeigt werden soll noch den Redakteur überlässt. Denk wieder an News. Filter nach Kategorie, mehrere Kategorien AND- oder OR-Verknüpft, Kategoriefilter negiert, absteigend oder aufsteigend sortiert, beschränkt auf Datum. All diese Optionen kann der Redakteur im News-Plugin selbst wählen. Und jetzt bau das mal als SOAP-Anfrage nach, damit sie im Frontend zum Synchronisationszeitram zu 100% auf den vom Redakteur gewählte Extbase-Filter-Query passt. ⇨ Sync zur Laufzeit erzeugt einen wahnsinnigen Kraut-und-Rüben-Code, bläst Dein Model auf und kostet RAM im Web-Request. > Leider liefert der Webservice kein Änderungsdatum o.Ä. an dem ich entscheiden > könnte, ob aktualisieren, nicht aktualisieren oder löschen. Bleibt also > nichts Anderes übrig als lokal zu entscheiden mittels timestamp, oder? Wenn Dir der SOAP-Request keine Verändungsinformationen gibt, also weder eine Objekt-Version noch ein Änderungsdatum, dann kannst Du überhaupt nichts entscheiden. Dann musst Du wohl oder übel das Objekt speichern wenn Du es bekommst. > Da hast du natürlich recht. Ich werde also die getrennte Lösung per Scheduler > vorziehen. Ich würde wirklich genau einen einzigen Sync-Durchlauf per Scheduler machen der das komplette Model lokal aufbaut. Anschließend kannst Du in Deinem lokalen Model noch filtern und sortieren wie Du lustig bist. Kein Filter, keine Sortierung. Der Scheduler-Durchlauf muss auch überhaupt nicht mit Extbase arbeiten. Mindestens die Datenmanipulation kann – gerade wenn es möglicherweise viele Daten sind – auch einfach durch den DataHandler passieren. Beste Grüße, Stephan Schuler Web-Entwickler | netlogix Web Solutions Telefon: +49 (911) 539909 - 0 E-Mail: stephan.schu...@netlogix.de Web: websolutions.netlogix.de Neu: Wir sind Amazon Web Services Partner. Mehr erfahren: https://websolutions.netlogix.de/technologie/amazon-web-services-aws netlogix GmbH & Co. KG IT-Services | IT-Training | Web Solutions Neuwieder Straße 10 | 90411 Nürnberg Telefon: +49 (911) 539909 - 0 | Fax: +49 (911) 539909 - 99 E-Mail: i...@netlogix.de | Web: http://www.netlogix.de netlogix GmbH & Co. KG ist eingetragen am Amtsgericht Nürnberg (HRA 13338) Persönlich haftende Gesellschafterin: netlogix Verwaltungs GmbH (HRB 20634) Umsatzsteuer-Identifikationsnummer: DE 233472254 Geschäftsführer: Matthias Schmidt ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo, Es wäre schön, wenn ich Dich mit Namen ansprechen könnte. Ein sinnvoller Absender und eine Grußformel an Ende wäre dabei hilfreich. Hab mein Profil mal angepasst, aber keine Ahnung, ob und wann das auf das Forum durchschlägt. Ich würde das nach Möglichkeit entkoppeln und per Scheduler synchronisieren. Eine Synchronisation zur Laufzeit mit gleichzeitigem lokalem persistenten Model ist keine gute Idee, dann machst Du alles von Hand. Angefangen damit, dass Du Dir überlegen musst, welcher dieser Requests jetzt diese Daten aktualisieren muss und welche nicht. Sprich: Du musst Dir bei jedem Objekt das „last synced" merken um zu entscheiden, ob das zu synchronisieren ist oder nicht. Natürlich hat der Datensatz bereits das Attribut „tstamp" womit die letzte Modifikation in der Datenbank gemeint ist. Aber dieser tstamp gehört ja eigentlich nicht in deine Domäne. Das ist ein Hilfsmittel, ein Werkzeug. Ein eine Object-Property des Extbase Domain-Models würde ich den tstamp nicht mappen solange er nicht wirklich im Frontend für den Benutzer als „letzte Änderung: Vor 15 Minuten" o.ä. angezeigt werden soll. Wenn Du die Synchronisation in einen Scheduler packst ist klar: Jedes Mal wenn der läuft synchronisiert der. Aber wie mache ich es dann? Ich muss ja irgendwie aus der XML-Antwort meine Objekte basteln, über die ich dann im Fluid Template iteriere und die Tabellen zusammensetze. Die Aufteilung in den Teil der sich geändert hat und den Teil der sich nicht geändert hat kannst Du im Scheduler immer noch durchführen. Lass Dir eine Liste aller Objekte geben, evtl. mit reduziertem Datenumfang. Diejenigen die im SOAP-Request ein Änderungsdatum neuer als tstamp lokal haben sind lokal zu aktualisieren. Die die im SOAP-Request ein Änderungsdatum älter als tstamp haben kannst Du in Ruhe lassen. Die die lokal existieren aber nicht über den SOAP-Request kommen musst Du lokal löschen. Insbesondere die Entscheidung welches Objekt ggf. zu löschen ist kannst Du nur über Bande treffen wenn Du im Controller des Frontend-Requests synchronisierst. Leider liefert der Webservice kein Änderungsdatum o.Ä. an dem ich entscheiden könnte, ob aktualisieren, nicht aktualisieren oder löschen. Bleibt also nichts anderes übrig als lokal zu entscheiden mittels timestamp, oder? Weiterhin bringt Dir bei der Synchronisation im Frontend die Extbase-Persistenz eigentlich keinen relevanten Vorteil. Wenn Du stattdessen den Plugin eine Stunde lang als HTML-Snippet cachen kannst, genügt es, die Objekte oer SOAP zu holen, an Fluid zu übergeben und nach dem PHP-Request wieder zu vergessen. Der dritte, weit schlimmste Nachteil der Synchronisation im Controller ist, dass Du Deine Frontend-Laufzeit von fremden Servern abhängig machst. Wenn der SOAP-Server mal nen schlechten Tag hat und ein paar Sekunden für die Antwort braucht, oder gar nicht antwortet, weil irgendwas hängt, dann hängt auch Dein Frontend. Solange Du Deine Daten nicht in der Datenbank als geändert schreibst (sprich: die Nicht-Antwort des SOAP-Servers als leeres Result und damit Löschanweisung interpretierst) bedeutet das für Dein Frontend, dass mehrfache Anfragen im Frontend jeweils parallel auf die Idee kommen, für die Synchronisation zuständig zu sein, und alle hängen am hängenden SOAP-Server fest. Dein Webserver hat ja nicht unendlich viel Arbeitsspeicher und kann damit nicht unendlich viele PHP-Prozesse gleichzeitig bedienen. Wenn Du für das Betriebssystem 1GB RAM abziehst und jedem PHP-Prozess 64MB RAM spendierst kansnt Du Dir ausrechnen, wie viele parallele PHP-Prozesse Du Dir erlauben kannst ohne dass der Server swappen muss. Die Zahl liegt mit großer Wahrscheinlichkeit im unteren zweistelligen Bereich. Wenn die Seite mit der Tabelle jetzt etwas Load hat, vielleicht vom ein oder anderen Crawler gefunden wird, wenn Du jetzt auch noch ungeduldige Webseitenbesucher hast die nach 10 Sekunden Ladekringel gleich auf reload drücken, dann hast Du sehr schnell alle Deine PHP-Prozesse damit belegt, auf den nicht mehr reagierenden SOAP-Server zu warten. Ab diesem Zeitpunkt sind Frontend und Backend nicht mehr erreichbar. Da hast du natürlich recht. Ich werde also die getrennte Lösung per Scheduler vorziehen. Gruß, Fabian ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo! Es wäre schön, wenn ich Dich mit Namen ansprechen könnte. Ein sinnvoller Absender und eine Grußformel an Ende wäre dabei hilfreich. Ich würde das nach Möglichkeit entkoppeln und per Scheduler synchronisieren. Eine Synchronisation zur Laufzeit mit gleichzeitigem lokalem persistenten Model ist keine gute Idee, dann machst Du alles von Hand. Angefangen damit, dass Du Dir überlegen musst, welcher dieser Requests jetzt diese Daten aktualisieren muss und welche nicht. Sprich: Du musst Dir bei jedem Objekt das „last synced“ merken um zu entscheiden, ob das zu synchronisieren ist oder nicht. Natürlich hat der Datensatz bereits das Attribut „tstamp“ womit die letzte Modifikation in der Datenbank gemeint ist. Aber dieser tstamp gehört ja eigentlich nicht in deine Domäne. Das ist ein Hilfsmittel, ein Werkzeug. Ein eine Object-Property des Extbase Domain-Models würde ich den tstamp nicht mappen solange er nicht wirklich im Frontend für den Benutzer als „letzte Änderung: Vor 15 Minuten“ o.ä. angezeigt werden soll. Wenn Du die Synchronisation in einen Scheduler packst ist klar: Jedes Mal wenn der läuft synchronisiert der. Die Aufteilung in den Teil der sich geändert hat und den Teil der sich nicht geändert hat kannst Du im Scheduler immer noch durchführen. Lass Dir eine Liste aller Objekte geben, evtl. mit reduziertem Datenumfang. Diejenigen die im SOAP-Request ein Änderungsdatum neuer als tstamp lokal haben sind lokal zu aktualisieren. Die die im SOAP-Request ein Änderungsdatum älter als tstamp haben kannst Du in Ruhe lassen. Die die lokal existieren aber nicht über den SOAP-Request kommen musst Du lokal löschen. Insbesondere die Entscheidung welches Objekt ggf. zu löschen ist kannst Du nur über Bande treffen wenn Du im Controller des Frontend-Requests synchronisierst. Weiterhin bringt Dir bei der Synchronisation im Frontend die Extbase-Persistenz eigentlich keinen relevanten Vorteil. Wenn Du stattdessen den Plugin eine Stunde lang als HTML-Snippet cachen kannst, genügt es, die Objekte oer SOAP zu holen, an Fluid zu übergeben und nach dem PHP-Request wieder zu vergessen. Der dritte, weit schlimmste Nachteil der Synchronisation im Controller ist, dass Du Deine Frontend-Laufzeit von fremden Servern abhängig machst. Wenn der SOAP-Server mal nen schlechten Tag hat und ein paar Sekunden für die Antwort braucht, oder gar nicht antwortet, weil irgendwas hängt, dann hängt auch Dein Frontend. Solange Du Deine Daten nicht in der Datenbank als geändert schreibst (sprich: die Nicht-Antwort des SOAP-Servers als leeres Result und damit Löschanweisung interpretierst) bedeutet das für Dein Frontend, dass mehrfache Anfragen im Frontend jeweils parallel auf die Idee kommen, für die Synchronisation zuständig zu sein, und alle hängen am hängenden SOAP-Server fest. Dein Webserver hat ja nicht unendlich viel Arbeitsspeicher und kann damit nicht unendlich viele PHP-Prozesse gleichzeitig bedienen. Wenn Du für das Betriebssystem 1GB RAM abziehst und jedem PHP-Prozess 64MB RAM spendierst kansnt Du Dir ausrechnen, wie viele parallele PHP-Prozesse Du Dir erlauben kannst ohne dass der Server swappen muss. Die Zahl liegt mit großer Wahrscheinlichkeit im unteren zweistelligen Bereich. Wenn die Seite mit der Tabelle jetzt etwas Load hat, vielleicht vom ein oder anderen Crawler gefunden wird, wenn Du jetzt auch noch ungeduldige Webseitenbesucher hast die nach 10 Sekunden Ladekringel gleich auf reload drücken, dann hast Du sehr schnell alle Deine PHP-Prozesse damit belegt, auf den nicht mehr reagierenden SOAP-Server zu warten. Ab diesem Zeitpunkt sind Frontend und Backend nicht mehr erreichbar. Um Himmels Willen führ Kommunikation mit fremden Servern erstens mit dem geringstmöglichen Timeout durch und zweitens sofern nur irgend möglich asynchron. Beste Grüße, Stephan. Stephan Schuler Web-Entwickler | netlogix Web Solutions Telefon: +49 (911) 539909 - 0 E-Mail: stephan.schu...@netlogix.de Web: websolutions.netlogix.de Neu: Wir sind Amazon Web Services Partner. Mehr erfahren: https://websolutions.netlogix.de/technologie/amazon-web-services-aws netlogix GmbH & Co. KG IT-Services | IT-Training | Web Solutions Neuwieder Straße 10 | 90411 Nürnberg Telefon: +49 (911) 539909 - 0 | Fax: +49 (911) 539909 - 99 E-Mail: i...@netlogix.de | Web: http://www.netlogix.de netlogix GmbH & Co. KG ist eingetragen am Amtsgericht Nürnberg (HRA 13338) Persönlich haftende Gesellschafterin: netlogix Verwaltungs GmbH (HRB 20634) Umsatzsteuer-Identifikationsnummer: DE 233472254 Geschäftsführer: Matthias Schmidt ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Ok, mit so einer ausführlichen Atnwort hab ich nicht gerechnet. Danke! Quote: Stephan Schuler wrote on Fri, 11 August 2017 14:02 Eine Variante wäre, die Remote-Daten als lokale Domäne abzubilden und per Scheduler einen Import zu bauen. Wenn z.B. ein beliebiges JSON- oder XML-Format verwendet wird um Daten bereitzustellen die in TYPO3 als News angezeigt werden sollen bietet es sich ja an, alle paar Minuten die Daten remote abzufragen und in lokale News-Records zu überführen. Der Vorteil daran ist natürlich, dass man keinen gesonderten Renderingprozess für diese News konfigurieren muss, wenn es ohnehin schon anderweitige, lokale News gibt. Das ist der Weg, den ich so jetzt auch gegangen wäre. Vorab zum Verständnis grad nochmal was ich brauche: Ich möchte eine Extension bauen, die den Redakteuren ein Frontend Plugin zur Verfügung stellt, welches sie auf beliebigen Seiten einfügen können. Dieses Plugin soll letztendlich Daten eines Webservice (genauer handelt es sich dabei um Veranstaltungsdaten (Termin, Ort, etc.)) tabellarisch aufbereiten und anzeigen. Der Redakteuer hätte in der Plugin Konfiguration gewisse Einstellungsmöglichkeiten, was genau angezeigt werden soll (aus diesen Einstellungen wird die Request für den Webservice gebaut). Die angezeigten Daten müssen von Zeit zu Zeit aktualisiert werden (nehmen wir als Richtwert mal an das die Daten immer 1 Stunde lang gültig sind). Stellt sich für mich nur noch die Frage, ob ich die Aktualisierung der Remote-Daten per Scheduler oder im Controller durchführe. Ersteres scheint mir eigentlich der sauberere Weg zu sein, allerdings sehe ich beim Controller den Vorteil, dass nur Einträge aktualisiert werden, die auch abgefragt werden. Seiten mit dem Plugin, die nicht aufgerufen werden, müssen ja nicht aktuell sein. Nachteil wäre halt, dass es jede Stunde einen Nutzer trifft, der einige Sekunden warten muss, bis die Remote-Daten neu abgefragt wurden. Auch wenn man in eine lokale Suche die Remote-Daten integrieren möchte bietet sich dieser Schritt an. Wenn man erst einen Import von einer Remote-API in lokale Datensätze durchführt, kann im Folgeschritt z.B. ein Solr-Indexing-Task die Daten in den Solr schaufeln und sie sind im Frontend über die Suche verfügbar. Dabei sollte der Import natürlich über den TYPO3 DataHandler durchgeführt werden, weil das die zentrale Stelle ist, die sowohl eine für Redakteure nachvollziehbare History erzeugt also auch der API-Call, an den sich wiederum Record-Indexer wie eben Solr hängen um innerhalb von TYPO3 über Datenänderungen informiert zu werden. Auch was Caching innerhalb einer TYPO3-Seite betrifft (Cache-Tags im Caching-Framework) ist die Verwendung des DataHandler dringend angeranten. Eine Verfügbarkeit der Daten über eine Suche ist nicht nötig. Eine weitere Möglichkeit ist ein Runtime-Cache. Der API-Aufruf ist sicherlich in irgendeiner Form ein HTTP GET-Request. Das heißt hier gibt es eine URL aus der sich ein Cache-Identifier ableiten lässt sowie einen Response-Body der der Cache-Content sein kann. Hier rate ich dringend dazu, nicht irgendeine selbst erfundene Datenbankstruktur zu verwenden, sondern das Caching-Framework. Für die Speicherung der Daten gibt es unterschiedliche Backends, nämlich u.a. dateibasiert, datenbankbasiert, memcache oder redis. Je nach Bedarf und Verfügbarkeit. Dem Konsumenten des Caches gegenüber stellt man die Daten dan entweder über das Variable-Frontend zur Verfügung (z.B. wenn es sich um Array oder Objekte handelt) oder über das String-Frontend (wenn der Konsument den Text-Body bekommen soll). Wenn der Cache richtig konfiguriert ist, lässt er sich über die „Clear Cache"-Buttons im Backend rechts oben ganz einfach leeren, wodurch das auch von Redakteuren bedient werden kann. Oder auch ein „Clear all Caches" wie man es ja vermutlich im Rahmen jedes Code-Deployments anstößt (Stichwort CLI-API!) nimmt das Caching-Framework, man muss sich also nicht selbst darum kümmern. Ja, der Webservice wird über eine SOAP-Request angesprochen. Werde mir diese Möglichkeit mal genauer ansehen. In beiden Fällen ist natürlich kein Weg beschrieben, wie Inhaltsänderungen des Providers an TYPO3 kommuniziert werden können. Das heißt, dass Du Dir eine Cache-Lifetime ausdenken musst die im Zweifelsfall zu kurz oder zu lang ist. Eine Lifetime von wenigen Minuten könnte dafür sorgen, dass Du trotzdem an ein anbieterseitiges Request-Limit stößt. Eine Lifetime von mehreren Minuten dagegen sorgt immer für panische Anrufe von Redakteuren, warum die Inhaltsänderung nicht sofort auch in TYPO3 sichtbar ist. Hier sollte es im Idealfall Empfehlungen des API-Providers geben an die man sich halten kann. Dann lassen sich diese Empfehlungen dem Kunden kommunizieren und die panischen Redakteure können mit Fakten beruhigt werden. Wenn es sich um einen HTTP GET-Request handelt der seinerseits Cache-Header enthält,
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo zusammen. Es gibt natürlich unzählige Ansätze. Eine Variante wäre, die Remote-Daten als lokale Domäne abzubilden und per Scheduler einen Import zu bauen. Wenn z.B. ein beliebiges JSON- oder XML-Format verwendet wird um Daten bereitzustellen die in TYPO3 als News angezeigt werden sollen bietet es sich ja an, alle paar Minuten die Daten remote abzufragen und in lokale News-Records zu überführen. Der Vorteil daran ist natürlich, dass man keinen gesonderten Renderingprozess für diese News konfigurieren muss, wenn es ohnehin schon anderweitige, lokale News gibt. Auch wenn man in eine lokale Suche die Remote-Daten integrieren möchte bietet sich dieser Schritt an. Wenn man erst einen Import von einer Remote-API in lokale Datensätze durchführt, kann im Folgeschritt z.B. ein Solr-Indexing-Task die Daten in den Solr schaufeln und sie sind im Frontend über die Suche verfügbar. Dabei sollte der Import natürlich über den TYPO3 DataHandler durchgeführt werden, weil das die zentrale Stelle ist, die sowohl eine für Redakteure nachvollziehbare History erzeugt also auch der API-Call, an den sich wiederum Record-Indexer wie eben Solr hängen um innerhalb von TYPO3 über Datenänderungen informiert zu werden. Auch was Caching innerhalb einer TYPO3-Seite betrifft (Cache-Tags im Caching-Framework) ist die Verwendung des DataHandler dringend angeranten. Eine weitere Möglichkeit ist ein Runtime-Cache. Der API-Aufruf ist sicherlich in irgendeiner Form ein HTTP GET-Request. Das heißt hier gibt es eine URL aus der sich ein Cache-Identifier ableiten lässt sowie einen Response-Body der der Cache-Content sein kann. Hier rate ich dringend dazu, nicht irgendeine selbst erfundene Datenbankstruktur zu verwenden, sondern das Caching-Framework. Für die Speicherung der Daten gibt es unterschiedliche Backends, nämlich u.a. dateibasiert, datenbankbasiert, memcache oder redis. Je nach Bedarf und Verfügbarkeit. Dem Konsumenten des Caches gegenüber stellt man die Daten dan entweder über das Variable-Frontend zur Verfügung (z.B. wenn es sich um Array oder Objekte handelt) oder über das String-Frontend (wenn der Konsument den Text-Body bekommen soll). Wenn der Cache richtig konfiguriert ist, lässt er sich über die „Clear Cache“-Buttons im Backend rechts oben ganz einfach leeren, wodurch das auch von Redakteuren bedient werden kann. Oder auch ein „Clear all Caches“ wie man es ja vermutlich im Rahmen jedes Code-Deployments anstößt (Stichwort CLI-API!) nimmt das Caching-Framework, man muss sich also nicht selbst darum kümmern. In beiden Fällen ist natürlich kein Weg beschrieben, wie Inhaltsänderungen des Providers an TYPO3 kommuniziert werden können. Das heißt, dass Du Dir eine Cache-Lifetime ausdenken musst die im Zweifelsfall zu kurz oder zu lang ist. Eine Lifetime von wenigen Minuten könnte dafür sorgen, dass Du trotzdem an ein anbieterseitiges Request-Limit stößt. Eine Lifetime von mehreren Minuten dagegen sorgt immer für panische Anrufe von Redakteuren, warum die Inhaltsänderung nicht sofort auch in TYPO3 sichtbar ist. Hier sollte es im Idealfall Empfehlungen des API-Providers geben an die man sich halten kann. Dann lassen sich diese Empfehlungen dem Kunden kommunizieren und die panischen Redakteure können mit Fakten beruhigt werden. Wenn es sich um einen HTTP GET-Request handelt der seinerseits Cache-Header enthält, könnte man sich auch an die halten. Wenn z.B. ein „Cache-Control: Max-Age“ kommt kann ich ausrechnen wie lange ich diesen Wert cachen darf. Wenn ein „Cache-Control: Private“ kommt brauch ich mit dem Caching gar nicht anfangen. Mir ist hierzu aber nichts bekannt das das durch eine Library abdecken würde. Wenn das im Rahmen Deines Projekts entsteht schreit das also nach einer Veröffentlichung. Wenn lediglich innerhalb eines einzigen TYPO3-Prozesses ein Request gecacht werden soll, würde ich trotzdem das Caching-Framework verwenden. Gemeint ist, wenn der gleiche GET-Request z.B. durch ViewHelper mehrmals vom gleichen TYPO3-Prozess abgeschickt wird. Man könnte zwar auf den ersten Blick auf die Idee kommen, einfach eine Singleton-Klasse zu schreiben die den Request unterdrückt, wenn für die URL bereits eine Response in einer Instanzvariable steht. Das wirft man allerdings komplett weg, wenn man das Caching über mehrere Prozesse ausdehnen will. Besser man verwendet gleich das Caching-Framework und stellt als Backend erst mal das „TransientMemoryBackend“ ein. Das ist nur innerhalb eines PHP-Prozesses gültig, d.h. der nächste Click startet wieder mit einem leeren Backend und macht einen neuen HTTP-Request. Wenn man allerdings später das Caching über mehrere Prozesse strecken möchte, gibt man einfach ein anderes Backend über die LocalConfiguration oder EnvironmentConfiguration an, ohne seinen PHP-Code anfassen zu müssen. Auch lassen sich so z.B. ein Stagingserver mit TransientMemoryBackend (weil der eh keine nennenswerte Last aber dafür ungeduldige Spielkinder als
Re: [TYPO3-german] Caching von Webserviceantworten
Quote: Stephan Bauer wrote on Thu, 10 August 2017 09:30 Hier gibt es die Github-Version vom Extension-Builder für 8.7: https://github.com/FriendsOfTYPO3/extension_builder/ Wie installiere ich den? Habe 8.7.4 im Composer Mode laufen und habe den Inhalt des git repos unter typo3conf/ext/extension_builder/ abgelegt. Nachdem ich ihn über den EM aktiviert habe und öffnen will kommt dieser fehler: Could not analyse class: "EBT\ExtensionBuilder\Controller\BuilderModuleController" maybe not loaded or no autoloader? Class EBT\ExtensionBuilder\Controller\BuilderModuleController does not exist Quote: Christian Platt (platti) wrote on Thu, 10 August 2017 09:48 Die Frage ist ja, wie häufig sich die Quelldaten erneuern 2 Ansätze... wenn z.B. einmal täglich sich die Daten ändern 1. On the fly Request kommt rein, man prüft, ob es schon einen Eintrag für den Tag gibt, wenn nein, lädt man die Daten und speichert die in der Datenbank. Ist schon ein Eintrah vorhanden, dann wird dieser ausgegeben. Werden die Daten häufiger erneuert,lässt sich das ähnlich umsetzen oder man schafft eine Methode, die nur die Daten in die DB schaufelt und ruft die regelmäßig auf. Das mit dem CommandController war nur ein Test unabhängig von dem "Caching-Problem" hier. Öfter als einen Tag müssen die Daten auf jeden Fall aktualisiert werden. Eher so jede Stunde, vielleicht sogar öfter. ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Die Frage ist ja, wie häufig sich die Quelldaten erneuern…. 2 Ansätze… wenn z.B. einmal täglich sich die Daten ändern 1. On the fly Request kommt rein, man prüft, ob es schon einen Eintrag für den Tag gibt, wenn nein, lädt man die Daten und speichert die in der Datenbank. Ist schon ein Eintrah vorhanden, dann wird dieser ausgegeben. Werden die Daten häufiger erneuert,lässt sich das ähnlich umsetzen oder man schafft eine Methode, die nur die Daten in die DB schaufelt und ruft die regelmäßig auf. Genau - anfangen würde ich auch im Extensionbuilder 7.6! Mit freundlichen Grüßen Christian Platt > Am 10.08.2017 um 07:53 schrieb f zuerker: > > Da ich später 8.7 nutze (und es dafür ja noch keinen Extension Builder gibt), > würde ich dann einfach zum Erstellen des Grundgerüsts 7.6 mit Extension > Builder aufsetzten und später auf 8.7 "portieren"? Alles manuell direkt für > 8.7 anlegen ist wahrscheinlich für einen Anfänger wie mich ziemlich > aufwendig, schätze ich. > > Müsste ich nicht eher den timestamp in der Datenbank checken, um zu sehen, ob > ich die Daten aus der Datenbank an die View gebe oder die schon so alt sind, > dass ich den Webservice abfrage und neu in die Datenbank schreibe? Oder habe > ich dich da falsch verstanden? > > Das müsste ich noch genauer schauen. Testweise hab ich auch schon mal einen > CommandController gebastelt, der einmal am Tag nachts eine XML Datei > aktualisiert. Ab welcher Häufigkeit würde ich denn besser einen > Scheduler/CommandController nutzen? > ___ > TYPO3-german mailing list > TYPO3-german@lists.typo3.org > http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hier gibt es die Github-Version vom Extension-Builder für 8.7: https://github.com/FriendsOfTYPO3/extension_builder/ Grüße Stephan ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Da ich später 8.7 nutze (und es dafür ja noch keinen Extension Builder gibt), würde ich dann einfach zum Erstellen des Grundgerüsts 7.6 mit Extension Builder aufsetzten und später auf 8.7 "portieren"? Alles manuell direkt für 8.7 anlegen ist wahrscheinlich für einen Anfänger wie mich ziemlich aufwendig, schätze ich. Müsste ich nicht eher den timestamp in der Datenbank checken, um zu sehen, ob ich die Daten aus der Datenbank an die View gebe oder die schon so alt sind, dass ich den Webservice abfrage und neu in die Datenbank schreibe? Oder habe ich dich da falsch verstanden? Das müsste ich noch genauer schauen. Testweise hab ich auch schon mal einen CommandController gebastelt, der einmal am Tag nachts eine XML Datei aktualisiert. Ab welcher Häufigkeit würde ich denn besser einen Scheduler/CommandController nutzen? ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german
Re: [TYPO3-german] Caching von Webserviceantworten
Hallo f, Erweiterung mit den entsprechenden Daten des Webservices erstellen im Extensionbuiler... In der Erweiterung Webservice abfragen und mit Tabelle vergleichen. Wie häufig ändern sich die Daten? Evtl Scheduler machen, der den Webservice über eigene Klasse ausliesst und in DB schreibt…. Mit freundlichen Grüßen Christian Platt > Am 09.08.2017 um 11:56 schrieb f zuerker: > > Hallo, > > wie kann ich Antworten die ich von einem Webservice bekomme innerhalb einer > Extension cachen? > > Angenommen ich möchte ne Extension bauen, die mir Daten von einem Webservice > holt und in einem Fluid Template im Frontend ausgibt. Wie kann ich die > ankommenden Daten für eine gewisse Zeit cachen, sodass beim Aufruf der Seite > nicht jedesmal der Webservice abgefragt wird und man mehrere Sekunden warten > muss bis die Seite geladen ist. Geht das schon mit Typo3 "Boardmitteln" oder > bin ich auf was externes angewiesen? > > Vielen Dank > ___ > TYPO3-german mailing list > TYPO3-german@lists.typo3.org > http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german ___ TYPO3-german mailing list TYPO3-german@lists.typo3.org http://lists.typo3.org/cgi-bin/mailman/listinfo/typo3-german