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:
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
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in new issue
Block a user