Add scheduled task to update cached feeds

On large data set, generating the feed may take too long for an HTTP request.
So in this case user may want to update the cache with a scheduled task so the
requests are always answered directly using the cache.
This commit is contained in:
Cédric Krier committed 2024-04-16 18:43:37 +02:00
1 parent 215834f78f
commit cccdc1f1f7
6 files changed
+59 -5

No files matched your search

@@ -1,3 +1,4 @@
* Add scheduled task to update cached feeds
Version 7.2.0 - 2024-04-29
--------------------------
@@ -3,13 +3,14 @@
from trytond.pool import Pool
from . import product, routes, web
from . import ir, product, routes, web
__all__ = ['register', 'routes']
def register():
Pool.register(
ir.Cron,
product.UoM,
product.Template,
product.Product,
@@ -2,6 +2,16 @@
Usage
*****
.. _Scheduling Product Data Feed updates:
Scheduling Product Data Feed updates
====================================
You may want to define some "Scheduled tasks" :guilabel:`Update Web Shop
Product Data Feed` to keep the cache of the feeds up to date.
The task updates each feed already in the cache if their last modification was
before half of the `cache duration <config-web_shop.product_data_feed_cache>`.
.. _Fill Google Product Category:
Fill Google Product Category
+15
View File
@@ -0,0 +1,15 @@
# This file is part of Tryton. The COPYRIGHT file at the top level of
# this repository contains the full copyright notices and license terms.
from trytond.pool import PoolMeta
class Cron(metaclass=PoolMeta):
__name__ = 'ir.cron'
@classmethod
def __setup__(cls):
super().__setup__()
cls.method.selection.append(
('web.shop|update_product_data_feed_csv',
"Update Web Shop Product Data Feed"))
@@ -4,7 +4,7 @@
import os
import tempfile
from decimal import Decimal
from unittest.mock import Mock, patch
from unittest.mock import ANY, Mock, patch
from trytond.modules.account.tests import create_chart
from trytond.modules.company.tests import create_company, set_company
@@ -133,6 +133,12 @@ class WebShopProductDataFeedTestCase(ModuleTestCase):
os.path.dirname(__file__),
'google-products.csv')).read())
with patch.object(Shop, 'product_data_feed_csv') as feed:
Shop.update_product_data_feed_csv()
feed.assert_called_once_with(
'google', language=None, duration=ANY)
class WebShopProductDataFeedRouteTestCase(RouteTestCase):
"Test Web Shop Product Data Feed route"
+24 -3
View File
@@ -2,6 +2,7 @@
# this repository contains the full copyright notices and license terms.
import csv
import fnmatch
import os
import shutil
import tempfile
@@ -75,7 +76,25 @@ class Shop(metaclass=PoolMeta):
context['language'] = language
return context
def product_data_feed_csv(self, format, language=None):
@classmethod
def update_product_data_feed_csv(cls, shops=None):
if shops is None:
shops = cls.search([])
directory = _get_directory()
for shop in shops:
for name in fnmatch.filter(
os.listdir(directory),
f'{shop.name}-{shop.id}-*.csv'):
name = name[len(f'{shop.name}-{shop.id}-'):-len('.csv')]
if '-' in name:
format, language = name.rsplit('-', 1)
else:
format, language = name, None
shop.product_data_feed_csv(
format, language=language, duration=_duration / 2)
def product_data_feed_csv(self, format, language=None, duration=_duration):
transaction = Transaction()
directory = _get_directory()
if language:
@@ -85,10 +104,12 @@ class Shop(metaclass=PoolMeta):
filename = os.path.join(directory, filename)
try:
if (time.time() - os.path.getmtime(filename)) < _duration:
if (time.time() - os.path.getmtime(filename)) < duration:
return filename
except OSError:
pass
# Create the file so cron will update it
# even if this generation fails
open(filename, 'a').close()
with transaction.set_context(_product_data_language=language):
products, prices, taxes = self.get_products()