Dynamic Progress Bar

by
Odoo          
v 13.0 Third Party 686
Download for 13.0 series Deploy on Odoo.sh
You bought this module and need support ? Click here !
Technical name web_progress
LicenseLGPL-3
Also available in version v 12.0 v 11.0
Technical name web_progress
LicenseLGPL-3
Also available in version v 12.0 v 11.0

Dynamic Progress Bar

Progress bar for Odoo waiting screen, possibility to cancel an ongoing operation and a system tray menu for all operations in progress.

web_progress exists for Odoo 11.0, 12.0 and 13.0 (CE and EE).

Author: Grzegorz Marczyński

License: LGPL-3.

Copyright © 2019 Grzegorz Marczyński

Features

  • progress reporting for all standard Odoo import and export operations
  • system tray menu that lists ongoing operations initiated by the logged user (all operations visible to Administrator)
  • support for all operations initiated through UI and executed by planned activities (cron)
  • generator-like method to simply add progress reporting to any iteration (support for sub-iterations)

For developers

Typically when your code executes any long-term operation there is a loop over a collection in your code.

In order to report progress of the operation, wrap the collection with self.web_progress_iter(collection, msg="Message") or, if the collection is self (or other recordset), use a simpler version self.with_progress("Message")

Say, your operation's main method looks as follows:


    @api.multi
    def action_operation(self):
        for rec in self:
            rec.do_somethig()
            

then a progress-reporting-ready version would be:


    @api.multi
    def action_operation(self):
        for rec in self.web_progress_iter(self, msg="Message"):
            rec.do_something()
            

or a simpler version for recordsets:


    @api.multi
    def action_operation(self):
        for rec in self.with_progress(msg="Message"):
            rec.do_something()
        

Progress tracking may be added to sub-operations as well:


    @api.multi
    def action_operation(self):
        for rec in self.with_progress(msg="Message"):
            lines = rec.get_lines()
            for line in lines.with_progress("Sub-operation")
                line.do_something()
        

Release Notes

1.3 - 2019-07-15 - new functionality
  • estimated time left / total
1.2 - 2019-06-24 - fixes:
  • refactor global progress data
  • change progress template name to avoid clash with progressbar widget
1.1 - 2019-06-23 - fixes:
  • remove unecessary dependency on multiprocessing
  • fix memory leak in time-tracking internal data
1.0 - 2019-06-20 - initial version

Adding progress tracking to your code

Prerequisites

Progress reporting uses longpolling to send progress data from backend to web client, so make sure that the longpolling is operational before testing this module.

Simple case

Typically when your code executes any long-term operation there is a loop over a collection in your code.

In order to report progress of the operation, wrap the collection with self.web_progress_iter(collection, msg="Message")

Say, your operation's main method looks as follows:

@api.multi
def action_operation(self):
    for rec in self:
        rec.do_somethig()

Then a progress-reporting-ready version would be:

@api.multi
def action_operation(self):
    for rec in self.web_progress_iter(self, msg="Message"):
        rec.do_something()

or a simpler version for recordsets:

@api.multi
def action_operation(self):
    for rec in self.with_progress(msg="Message"):
        rec.do_something()

Progress tracking may be added to sub-operations as well:

@api.multi
def action_operation(self):
    for rec in self.with_progress(msg="Message"):
        lines = rec.get_lines()
        for line in lines.with_progress("Sub-operation")
            line.do_something()

Advanced case

This module adds methods web_progress_iter and with_progress to every Odoo model. The only difference between these methods is that web_progress_iter requires as its first parameter a collection to iterate upon and with_progress iterates always on self.

Both methods accept the following optional parameters:

  • msg (str): an operation description, the message to be shown in the progress report,
  • total (int): if provided, will be used as a length of the given collection, so len(collection) will never be called, which is essential when tracking progress of generators (default is None, i.e. len will be called),
  • cancellable (bool): whether cancelling the operation should be possible, i.e visible button "Cancel" (default is True),
  • log_level (str): which log level shall be used when logging progress (default is "info").
@api.multi
def action_operation(self, data, length):
    for row in self.web_progress_iter(data, total=length, msg="Message",
                                      cancellable=True, log_level="debug"):
        self.do_something(row)

Another approach

You can also add iteration progress reporting to any recordset by adding progress_iter=True to its context.

FAQ

In this section you will find answers to the common questions concerning progress reporting implemented in web_progress module.

How to report a problem or ask a question?

Please use the issue tracker of our GitHub repository to report problems or ask questions. You will find it here.

How the progress reporting works?

...

How each operation is identified?

  1. Web client injects a unique progress_code (UUID) into the context of every RPC call towards backend.
  2. Both web_progress_iter and with_progress convert the given collection (or generator) into an instance of a generator-like class that uses a progress_code from context to perform progress tracking while your code iterates upon the collection.
  3. Sheduled (cron) actions have their progress_code injected into the context by scheduler prior to their execution.

How often the progress is reported?

For each progress_code (i.e. a unique operation) the first interation (the first element) of the collection wrapped with web_progress_iter or with_progress is reported to the web client (via longpolling).

After that, the progress is reported in intervals of minimum 5 seconds (i.e. any access to any wrapped collection more than 5 seconds after the last reported progress is reported).

Also the final iteration (the last element) of the main wrapped collection (on the top-level) is reported.

What is the overhead of progress reporting?

...

How the operation cancelling works?

...

How multi-level progress reporting works?

...

Is the current transaction commited to make progress visible?

No. Progress reporting uses a fresh transaction for each progress report and cancelled operation verification; therefore, the main transation stays untouched and in total isolation.

However, it should be noted that since progress report records and longpolling messages are commited into the database, even if the main transaction is still not commited, the main transaction shall never inspect or change those records in order to avoid inter-transactional conflicts (update-in-parallel exceptions).

Is it possible to put an ongoing operation into background?

Yes, by pressing F5. Actually this is a standard Odoo behaviour that any long-term operation may be put into background by pressing F5. The difference here is that, thanks to system tray menu, user has possibility to follow the progress of ongoing background operations and to cancel them.

Beware that putting an operation to the background makes it impossible to interact further with the user after the operation is finished. So this is OK for data imports (unless there are import errors) and this is definitely not OK for data exports (or reports) that let the user download a generated file after the export operation is finished.

Does progress reporting work with reports?

Yes, you can iterate over the wrapped collections in QWeb reports and the progress will be visible to the user.

Please log in to comment on this module

  • The author can leave a single reply to each comment.
  • This section is meant to ask simple questions or leave a rating. Every report of a problem experienced while using the module should be addressed to the author directly (refer to the following point).
  • If you want to start a discussion with the author, please use the developer contact information. They can usually be found in the description.
Please choose a rating from 1 to 5 for this module.