Neuigkeiten
  • Die modified eCommerce Shopsoftware ist kostenlos, aber nicht umsonst.
    Spenden
  • Damit wir die modified eCommerce Shopsoftware auch zukünftig kostenlos anbieten können:
    Spenden
  • Thema: Produkt nach Aktualisierung aus Cache entfernen.

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Produkt nach Aktualisierung aus Cache entfernen.
    am: 23. August 2024, 18:45:45
    Hallo an das Forum.

    Wir verwenden den neuen Shop  v3.1.0 rev 16069 und Redis. Da wir unsere Produkte mehrfach am Tag updaten habe ich ein Smarty-Funktion geschrieben  um ein Produkt aus dem Cache zu entfernen und die Veränderung sofort sichtbar zu machen.  Es kommt bei uns sehr oft vor, das wir Lieferzeiten anpassen müssen, was leider durch den Cache erst nach einer gewissen Zeit angezeigt wird. Es gibt nichts ärgerlicheres als ein Produkt mit einer falschen Lieferzeit anzubieten und da ich kein Freund bin in Systemdateien einzugreifen(nur ärger bei späteren Updates) finde ich die Smary-Funktion wirklich ein feines Werkzeug.

    Hier mal meine Idee zur Lösung:

    function.invalidateProductCache.php

    Code: PHP  [Auswählen]
    <?php
    function smarty_function_invalidateProductCache($param, $smarty) {
       
            // Connect to Redis
        /*
            try {
            $redis = new Redis();
            $redis->connect(REDIS_SERVER, REDIS_PORT, REDIS_TIMEOUT);
            $redis->select(REDIS_DB);

            // List all keys in Redis
            $allKeys = $redis->keys('*'); // Fetch all keys
            echo "<div>Current Redis Cache Contents:</div><ul>";

            foreach ($allKeys as $key) {
                $value = $redis->get($key); // Get the value for the key
                echo "<li>Key: {$key}, Value: {$value}</li>";
            }
            echo "</ul>";

        } catch (Exception $e) {
            // Handle Redis connection errors
            echo "<div>Redis connection failed: " . $e->getMessage() . "</div>";
        }
            */

           
            // Check if PRODUCTS_ID is passed
        if (!isset($param['PRODUCTS_ID'])) {
            return; // No product ID, exit the function
        }

        $productId = (int)$param['PRODUCTS_ID'];

        // Get the last modified date from the products table
        $dbQuery_last_modified = xtDBquery("SELECT products_last_modified FROM products WHERE products_id='" . $productId . "'");
        $lastModified = null;
        while ($dbQueryResult_last_modified = xtc_db_fetch_array($dbQuery_last_modified, true)) {
            $lastModified = $dbQueryResult_last_modified['products_last_modified'];
        }

        // Debug: Output the last modified date
        //echo "<div>Last modified date for product ID {$productId}: {$lastModified}</div>";

        // Ensure lastModified was fetched correctly
        if (!isset($lastModified)) {
            return; // If no last_modified date, exit the function
        }

        // Convert the last modified date to a timestamp
        $lastModifiedTime = strtotime($lastModified);

        // Get the current time
        $currentTime = time();

        // Check if the product was modified in the last hour (3600 seconds)
        if (($currentTime - $lastModifiedTime) <= 3600) {

            // Include the modified_cache class
            require_once(DIR_FS_CATALOG . 'includes/classes/modified_cache.php');

            // Get the instance of modified_cache
            $cache = modified_cache::getInstance();
                   
                    // Construct the cache key for the product
            $cacheKey = 'cp_' . $productId;

            // Set the cache item for the product
            $cache->setId($cacheKey);

            // Delete the cache item
            $cache->clear($cacheKey);

            // Check if the cache was successfully deleted
            $item = $cache->getId();               
                   
            if ($item === null) {
                echo "<script>window.location.reload();</script>";
            }
        }
    }
    ?>
     

    Aufruf in der jeweiligen product_info html: {invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}}

    Wir haben im Backend die Lebenszeit auf 3600 gestellt.

    Ich habe das in meinen Testshop implementiert und es scheint gut zu laufen. Das Product wird nach einer Änderung innerhalb des Zeitraumes aus dem Cache entfernt und das Produkt wird sofort aktualisiert. So wie ich weiterhin sehe bleiben alle anderen Einträge dem Cache erhalten.
    Rundum kurz meine Frage, bevor ich mein Entwurf in den laufenden Betrieb übernehme. Seht ihr hier irgendwelche Schwachstellen oder Auswirkungen an die ich vielleicht nicht gedacht habe.

    Danke für euer Feedback.
    LG Oliver

    Linkback: https://www.modified-shop.org/forum/index.php?topic=43533.0
    Modulshop - Eine große Auswahl an neuen und hilfreichen Modulen für die modified eCommerce Shopsoftware

    Timm

    • Fördermitglied
    • Beiträge: 6.258
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #1 am: 23. August 2024, 21:12:34
    Moin

    Vorab ich kann nicht programmieren.

    Den Ansatz finde ich aber interessant, nur das entsprechende Produkt aus dem Cache zu entfernen.

    Ich hatte im Bugtracker angeregt einen „Cache warmer“ zu implementieren, der alle Seiten einmal aufruft, damit sie im Cache sind. Vielleicht ist deine Lösung die bessere/einfachere.

    Aber es geht ja nicht nur um die Produktseite, sondern auch um Kategorielistings oder Filter, wo der Artikel mit dabei ist. Weiß nicht ob dein Vorschlag das beinhaltet.

    Gruß Timm

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #2 am: 23. August 2024, 21:40:47
    Moin Timm.

    Danke für dein Feedback. Ich habe mich erst einmal nur um das jeweilige Produkt gekümmert. Die Impelmentierung einer Smarty-Funktion für das Listing ist die logische Kosnequenz. Da das System im Bereich der Listings sehr benutzerfreundlich gehalten ist, wäre mein nächster Schritt auch dieses für das Listing umzusetzen.

    LG Oliver

    GTB

    • modified Team
    • Gravatar
    • Beiträge: 6.306
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #3 am: 24. August 2024, 08:13:17
    Hallo,

    so einfach ist es nicht. Um alle Einträge zu löschen, müsstest du alle Cache IDs für das jeweilige Produkt kennen. Und es geht nicht nur um die Template Cache sondern auch um den Datenbank Cache.

    Du kannst für PHPFastcache die Tags aktivieren. Damit wird ein Tag mit der ProductsID geschrieben und du kannst dann alle Tags für einen Artikel löschen.

    Gruß Gerhard

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #4 am: 25. August 2024, 15:33:37
    Hallo Gerhard.

    Da hast du natürlich recht und ich werde mich damit noch genauer befassen müssen.

    Der Cache scheint in meiner ersten Version der Smarty-Function etwas hartnäckiger als gedach. Daher hier noch mal eine modifizierte Version.

    {nocache}{invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}}{/nocache}

    Code: PHP  [Auswählen]
    <?php
    function smarty_function_invalidateProductCache($param, $smarty) {
           
            $smarty->caching = Smarty::CACHING_OFF;
           
            // Check if PRODUCTS_ID is passed
        if (!isset($param['PRODUCTS_ID'])) {
            return; // No product ID, exit the function
        }  

            $productId = (int)$param['PRODUCTS_ID'];  // Cast to integer
           
            // Get the last modified date from the products table
            $dbQuery_last_modified = xtDBquery("SELECT SQL_NO_CACHE products_last_modified AS modified_date FROM products WHERE products_id='" . $productId . "'");
            $lastModified = null;
            while ($dbQueryResult_last_modified = xtc_db_fetch_array($dbQuery_last_modified, true)) {
                    $lastModified = $dbQueryResult_last_modified['modified_date'];
            }

            // Debug: Output the original database timestamp (to compare)
            //echo "<div>Database timestamp: {$lastModified}</div>";

            //Since the database is already in CEST, no need to convert
            //echo "<div>Last Modified Date for product ID {$productId}: {$lastModified}</div>";
           
           
            // Include the modified_cache class
            require_once(DIR_FS_CATALOG . 'includes/classes/modified_cache.php');

            // Get the instance of modified_cache
            $cache = modified_cache::getInstance();
                   
            $cacheKey = 'products_last_modified_' . $productId;

            // Clear cache first
            $cache->clear($cacheKey);

            // Fetch fresh data from the database
            $productData = xtDBquery("SELECT * FROM products WHERE products_id='$productId'");

            // Store fresh data in cache
            $cache->set($cacheKey, $productData);
                   
       
            // Ensure lastModified was fetched correctly
        if (!isset($lastModified)) {
            return; // If no last_modified date, exit the function
        }

        // Convert the last modified date to a timestamp
        $lastModifiedTime = strtotime($lastModified);

        // Get the current time
        $currentTime = time();

        // Check if the product was modified in the last hour (3600 seconds)
        if (($currentTime - $lastModifiedTime) <= 3600) {
                           
                    // Construct the cache key for the product
            $cacheKey = 'cp_' . $productId;

            // Set the cache item for the product
            $cache->setId($cacheKey);

            // Delete the cache item
            $cache->clear($cacheKey);

            // Check if the cache was successfully deleted
            $item = $cache->getId();               
                   
            if ($item === null) {
                echo "<script>window.location.reload();</script>";
            } else {
                //echo "<div>Failed to invalidate cache for key: {$cacheKey}</div>";
            }

        } else {
            //echo "<div>No cache invalidation needed for product ID: {$productId} (Last modification is older than 1 hour)</div>";
        }
    }
    ?>
     

    noRiddle (revilonetz)

    • Experte
    • Beiträge: 13.988
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #5 am: 25. August 2024, 15:58:40
    Da ich in deiner Function SQL_NO_CACHE sehe:
    Zitat von: MySQL Manual: https://dev.mysql.com/doc/refman/5.7/en/query-cache-in-select.html
    The query cache is deprecated as of MySQL 5.7.20, and is removed in MySQL 8.0.

    Außerdem:
    Mag mich irren und möchte niemandem zu nahe treten, habe noch keinen Shop gesehen der durch Nutzung des/der Caches schneller war, eher langsamer.

    Bei der Gelegenheit:
    Man sollte mal die Button-Bechriftung für "Templatecache leeren" ändern.
    Siehe dazu auch Ticket #2576

    Gruß,
    noRiddle

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #6 am: 25. August 2024, 16:10:54
    Oh, das sollte da gar nicht mehr drinnen stehen. Danke noRiddle.

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #7 am: 29. August 2024, 21:31:24
    Hallo.

    Ich habe jetzt alles ausgiebig getestet und seit ein paar Tagen ist die Smarty-Funktion im Live-Modus im Einsatz. Das gilt für die Produktseite, wie auch das Listing.

    Hier noch einmal die Zusammenfassung:

    function.invalidateProductCache.php im Smarty Verzeichnis des Templates.

    Code: PHP  [Auswählen]
    <?php
    function smarty_function_invalidateProductCache($param, $smarty) {
           
            $smarty->caching = Smarty::CACHING_OFF;
           
            // Check if PRODUCTS_ID is passed
        if (!isset($param['PRODUCTS_ID'])) {
            return; // No product ID, exit the function
        }  

            $productId = (int)$param['PRODUCTS_ID'];  // Cast to integer
           
            // Get the last modified date from the products table
            $dbQuery_last_modified = xtDBquery("SELECT products_last_modified AS modified_date FROM products WHERE products_id='" . $productId . "'");
            $lastModified = null;
            while ($dbQueryResult_last_modified = xtc_db_fetch_array($dbQuery_last_modified, true)) {
                    $lastModified = $dbQueryResult_last_modified['modified_date'];
            }
           
            // Include the modified_cache class
            require_once(DIR_FS_CATALOG . 'includes/classes/modified_cache.php');

            // Get the instance of modified_cache
            $cache = modified_cache::getInstance();
                   
            $cacheKey = 'products_last_modified_' . $productId;

            // Clear cache first
            $cache->clear($cacheKey);

            // Fetch fresh data from the database
            $productData = xtDBquery("SELECT * FROM products WHERE products_id='$productId'");

            // Store fresh data in cache
            $cache->set($cacheKey, $productData);          
       
            // Ensure lastModified was fetched correctly
        if (!isset($lastModified)) {
            return; // If no last_modified date, exit the function
        }

        // Convert the last modified date to a timestamp
        $lastModifiedTime = strtotime($lastModified);

        // Get the current time
        $currentTime = time();

        // Check if the product was modified in the last hour (3600 seconds)
        if (($currentTime - $lastModifiedTime) <= 3600) {
                           
                    // Construct the cache key for the product
            $cacheKey = 'cp_' . $productId;

            // Set the cache item for the product
            $cache->setId($cacheKey);

            // Delete the cache item
            $cache->clear($cacheKey);

            // Check if the cache was successfully deleted
            $item = $cache->getId();               
                   
            if ($item === null) {
                echo "<script>window.location.reload();</script>";
            }
        }
    }
    ?>
     

    In dem Verzeichniss product_info/ die jeweilige gewählte html Datei ergänzen. z.B. unter {config_load file="lang_`$language`.section" section="product_info"} mit {invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}}

    Beispiel:
    Code: PHP  [Auswählen]
    {config_load file="$language/lang_$language.conf" section="product_info"}
    {config_load file="lang_`$language`.custom"}
    {config_load file="lang_`$language`.section" section="product_info"}
    {invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}}.......
     

    Für das Listing die Datei im Verzeichnis includes/product_box.html

    Code: PHP  [Auswählen]
      {* BOXANSICHT *}
     
      {invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}} .....
     

    und  includes/product_row.html

    Code: PHP  [Auswählen]

      {* ROWANSICHT *}
     
      {invalidateProductCache PRODUCTS_ID={$PRODUCTS_ID}} .....
     

    Gruß Oliver

    noRiddle (revilonetz)

    • Experte
    • Beiträge: 13.988
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #8 am: 29. August 2024, 22:18:32
    Vorsorglich sei gesagt, habe nichts analytisch nachvollzogen, ich stolpere jedoch über die Query-Funktion die den Query-Cache benutzt, nämlich xtDBquery(). Macht das Sinn wenn man die aktuellsten Daten benötigt und ja genau den Cache aushebeln möchte ?

    Gruß,
    noRiddle

    Nice_Stuff

    • Frisch an Board
    • Beiträge: 70
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #9 am: 29. August 2024, 22:43:58
    Hallo noRiddle.
    Genau das war ja das Problem. Geht ein Kunde auf das Produkt und setzt das products_last_modified Datum z.B. vor 2 Tagen, kann der Vergleichsoperator ($currentTime - $lastModifiedTime) <= 3600 das zuletzt bearbeite Datum nicht mehr setzen, weil er sich das alte Datum aus dem Cache zieht.
    Daher das Modifizieren des Datums in dem aktuellen Cache, damit die Änderungen, wie Preis oder Lieferzeit sofort aus der aktualisierten Datenbank geladen werden.

    Gruß Oliver

    noRiddle (revilonetz)

    • Experte
    • Beiträge: 13.988
    • Geschlecht:
    Re: Produkt nach Aktualisierung aus Cache entfernen.
    Antwort #10 am: 30. August 2024, 11:55:20
    Wie gesagt, habe nichts analytisch nachvollzogen.
    Dieser Kommentar jedoch
    Code: PHP  [Auswählen]
            // Fetch fresh data from the database

    mit anschließender Cache-Query
    Code: PHP  [Auswählen]
            $productData = xtDBquery("SELECT * FROM products WHERE products_id='$productId'");

    scheint mir sich zu widersprechen, denn "fresh" ist "data" dann nicht.

    Gruß,
    noRiddle
    3 Antworten
    2801 Aufrufe
    13. November 2013, 22:41:42 von Matt
    2 Antworten
    2665 Aufrufe
    23. Oktober 2014, 09:40:07 von MHammer
    21 Antworten
    11937 Aufrufe
    05. August 2009, 23:35:47 von Kosmo
               
    anything