From d8ffe2087d4e023316b2b162347d0d32a8b975c6 Mon Sep 17 00:00:00 2001 From: Erick Birbe Date: Thu, 21 Nov 2019 16:46:32 +0000 Subject: [PATCH] [ADD] ir_sequence_standard_default: Use Standard instead No Gap sequence Set the implementation to "Standard" in all your current Sequences (ir.sequence) and all new sequences are created as "Standard" by default instead of "No Gap" implementation. **What's the problem Sequences with "No Gap" Implementation?** "No Gap" is the default value of sequences in Odoo. However, this kind of sequences cause more locks and can turn a database slow. Taking as example an invoice, if you assign an invoice number to one record, but it sill not finish the process, this process must end in order to another invoice could assign a new number and there was no gaps between the invoice numbers. It seems to be good at first sight. But the problem start when there is and chained process. Imagine that there is one user that executes a process that produces 100 invoices and these at the same time produces 100 journal entries that also use a consecutive (no gap) sequence. And also those invoices are sent to sign with and external institution (that could take 2 seconds in giving a response because of internet latency or server load), and maybe they made another calculations that makes them to take 5 seconds more for each invoice, and all this is chained to one single transaction. This means that for 8.5 minutes anybody else could confirm invoices, neither journal entries of the involved journals. Now, think there is 20 users that have to execute a similar process. The problem turns exponential. If another user comes to make an operation with the same jornal it will thrown a concurrency failure. You can mitigate it if you segment each transaction and don't chain them. It means, making commit for each invoice or process. It reduces the probability that there is a concurrency error or a lock wait. However, it still not solve it completely. **Why to use Sequences with "Standard" Implementation?** If you use the standard sequence of PosgreSQL, it doesn't lock because at the moment the request is done, the next sequence number it is changed in an isolated transaction, and it have not to wait the other transaction to end. However, if the transaction produces a rollback, this sequence isn't reverted, it means, it's lost. It may be not not serious because when you cancel or remove records that number is lost too. **What this module does?** To eliminate completely that concurrency/slowness problem, this module changes all the sequences (ir.sequence) implementation from "No Gap" to "Standard" with the awareness that it will skip numbers. In the majority of database models and many users projects there is no problem with that jump occurs. Also, all newly created sequences will be by default in "Standard" implementation. --- ir_sequence_standard_default/README.rst | 137 ++++++ ir_sequence_standard_default/__init__.py | 6 + ir_sequence_standard_default/__manifest__.py | 23 + .../models/__init__.py | 4 + .../models/res_config_settings.py | 16 + .../readme/CONTRIBUTORS.rst | 3 + .../readme/DESCRIPTION.rst | 52 ++ .../static/description/icon.png | Bin 0 -> 9455 bytes .../static/description/index.html | 455 ++++++++++++++++++ .../tests/__init__.py | 5 + .../tests/test_sequence_standard_default.py | 46 ++ .../views/res_config_settings_views.xml | 31 ++ .../wizard/__init__.py | 4 + .../wizard/sequence_standard_default.py | 42 ++ .../sequence_standard_default_views.xml | 32 ++ 15 files changed, 856 insertions(+) create mode 100644 ir_sequence_standard_default/README.rst create mode 100644 ir_sequence_standard_default/__init__.py create mode 100644 ir_sequence_standard_default/__manifest__.py create mode 100644 ir_sequence_standard_default/models/__init__.py create mode 100644 ir_sequence_standard_default/models/res_config_settings.py create mode 100644 ir_sequence_standard_default/readme/CONTRIBUTORS.rst create mode 100644 ir_sequence_standard_default/readme/DESCRIPTION.rst create mode 100644 ir_sequence_standard_default/static/description/icon.png create mode 100644 ir_sequence_standard_default/static/description/index.html create mode 100644 ir_sequence_standard_default/tests/__init__.py create mode 100644 ir_sequence_standard_default/tests/test_sequence_standard_default.py create mode 100644 ir_sequence_standard_default/views/res_config_settings_views.xml create mode 100644 ir_sequence_standard_default/wizard/__init__.py create mode 100644 ir_sequence_standard_default/wizard/sequence_standard_default.py create mode 100644 ir_sequence_standard_default/wizard/sequence_standard_default_views.xml diff --git a/ir_sequence_standard_default/README.rst b/ir_sequence_standard_default/README.rst new file mode 100644 index 000000000..14948f4f0 --- /dev/null +++ b/ir_sequence_standard_default/README.rst @@ -0,0 +1,137 @@ +============================== +IrSequence Standard by Default +============================== + +.. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + !! This file is generated by oca-gen-addon-readme !! + !! changes will be overwritten. !! + !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +.. |badge1| image:: https://img.shields.io/badge/maturity-Beta-yellow.png + :target: https://odoo-community.org/page/development-status + :alt: Beta +.. |badge2| image:: https://img.shields.io/badge/licence-AGPL--3-blue.png + :target: http://www.gnu.org/licenses/agpl-3.0-standalone.html + :alt: License: AGPL-3 +.. |badge3| image:: https://img.shields.io/badge/github-OCA%2Fserver--tools-lightgray.png?logo=github + :target: https://github.com/OCA/server-tools/tree/12.0/ir_sequence_standard_default + :alt: OCA/server-tools +.. |badge4| image:: https://img.shields.io/badge/weblate-Translate%20me-F47D42.png + :target: https://translation.odoo-community.org/projects/server-tools-12-0/server-tools-12-0-ir_sequence_standard_default + :alt: Translate me on Weblate +.. |badge5| image:: https://img.shields.io/badge/runbot-Try%20me-875A7B.png + :target: https://runbot.odoo-community.org/runbot/149/12.0 + :alt: Try me on Runbot + +|badge1| |badge2| |badge3| |badge4| |badge5| + +Set the implementation to "Standard" in all your current Sequences +(ir.sequence) and all new sequences are created as "Standard" by default +instead of "No Gap" implementation. + +What's the problem with "No Gap" Sequence Implementations +========================================================= + +"No Gap" is the default value of sequences in Odoo. However, this kind of +sequences cause more locks and can turn a database slow. + +Taking as example an invoice, if you assign an invoice number to one record, +but it sill not finish the process, this process must end in order to another +invoice could assign a new number and there was no gaps between the invoice +numbers. It seems to be good at first sight. But the problem starts when there +is a chained process. + +Imagine that there is one user that executes a process that produces 100 +invoices and these at the same time produces 100 journal entries that also use +a consecutive (no gap) sequence. And also those invoices are sent to sign with +and external institution (that could take 2 seconds in giving a response +because of internet latency or server load), and maybe they made another +calculations that makes them to take 5 seconds more for each invoice, and all +this is chained to one single transaction. This means that for 8.5 minutes +anybody else could confirm invoices, neither journal entries of the involved +journals. + +Now, think there is 20 users that have to execute a similar process. The +problem turns exponential. If another user comes to make an operation with the +same jornal it will thrown a concurrency failure. + +You can mitigate it if you segment each transaction and don't chain them. It +means, making commit for each invoice or process. It reduces the +probability that there is a concurrency error or a lock wait. However, it still +not solve it completely. + +Why to use Sequences with "Standard" Implementation +=================================================== + +If you use the standard sequence of PosgreSQL, it doesn't lock because at the +moment the request is done, the next sequence number it is changed in an +isolated transaction, and it have not to wait the other transaction to end. +However, if the transaction produces a rollback, this sequence isn't reverted, +it means, it's lost. It may be not not serious because when you cancel or +remove records that number is lost too. + +What this module does +===================== + +To eliminate completely that concurrency/slowness problem, this module changes +all the sequences (ir.sequence) implementation from "No Gap" to "Standard" with +the awareness that it will skip numbers. In the majority of database models +and many users projects there is no problem with that jump occurs. + +**Table of contents** + +.. contents:: + :local: + +Bug Tracker +=========== + +Bugs are tracked on `GitHub Issues `_. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +`feedback `_. + +Do not contact contributors directly about support or help with technical issues. + +Credits +======= + +Authors +~~~~~~~ + +* Vauxoo + +Contributors +~~~~~~~~~~~~ + +- Moises López +- Erick Birbe + + +Maintainers +~~~~~~~~~~~ + +This module is maintained by the OCA. + +.. image:: https://odoo-community.org/logo.png + :alt: Odoo Community Association + :target: https://odoo-community.org + +OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use. + +.. |maintainer-moylop260| image:: https://github.com/moylop260.png?size=40px + :target: https://github.com/moylop260 + :alt: moylop260 +.. |maintainer-ebirbe| image:: https://github.com/ebirbe.png?size=40px + :target: https://github.com/ebirbe + :alt: ebirbe + +Current `maintainers `__: + +|maintainer-moylop260| |maintainer-ebirbe| + +This module is part of the `OCA/server-tools `_ project on GitHub. + +You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute. diff --git a/ir_sequence_standard_default/__init__.py b/ir_sequence_standard_default/__init__.py new file mode 100644 index 000000000..bc2aac796 --- /dev/null +++ b/ir_sequence_standard_default/__init__.py @@ -0,0 +1,6 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import models +from . import wizard +from . import tests diff --git a/ir_sequence_standard_default/__manifest__.py b/ir_sequence_standard_default/__manifest__.py new file mode 100644 index 000000000..ff232cb30 --- /dev/null +++ b/ir_sequence_standard_default/__manifest__.py @@ -0,0 +1,23 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + + +{ + 'name': 'IrSequence Standard by Default', + 'summary': 'Use Standard implementation of ir.sequence instead of NoGap', + 'version': '12.0.1.0.0', + 'author': 'Vauxoo, Odoo Community Association (OCA)', + 'website': 'https://github.com/OCA/server-tools', + 'maintainers': ['moylop260', 'ebirbe'], + 'license': 'AGPL-3', + 'category': 'Tools', + 'depends': [ + 'base_setup', + ], + 'data': [ + 'views/res_config_settings_views.xml', + 'wizard/sequence_standard_default_views.xml', + ], + 'installable': True, + 'application': False, +} diff --git a/ir_sequence_standard_default/models/__init__.py b/ir_sequence_standard_default/models/__init__.py new file mode 100644 index 000000000..0ae25614e --- /dev/null +++ b/ir_sequence_standard_default/models/__init__.py @@ -0,0 +1,4 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import res_config_settings diff --git a/ir_sequence_standard_default/models/res_config_settings.py b/ir_sequence_standard_default/models/res_config_settings.py new file mode 100644 index 000000000..5d3468189 --- /dev/null +++ b/ir_sequence_standard_default/models/res_config_settings.py @@ -0,0 +1,16 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo import api, models + + +class ResConfigSettings(models.TransientModel): + + _inherit = "res.config.settings" + + @api.multi + def action_change_all_sequences(self): + self.ensure_one() + action = self.env.ref( + 'ir_sequence_standard_default.action_sequence_standard_default') + return action.read()[0] diff --git a/ir_sequence_standard_default/readme/CONTRIBUTORS.rst b/ir_sequence_standard_default/readme/CONTRIBUTORS.rst new file mode 100644 index 000000000..1ed71719b --- /dev/null +++ b/ir_sequence_standard_default/readme/CONTRIBUTORS.rst @@ -0,0 +1,3 @@ +- Moises López +- Erick Birbe + diff --git a/ir_sequence_standard_default/readme/DESCRIPTION.rst b/ir_sequence_standard_default/readme/DESCRIPTION.rst new file mode 100644 index 000000000..8e87d8f65 --- /dev/null +++ b/ir_sequence_standard_default/readme/DESCRIPTION.rst @@ -0,0 +1,52 @@ +Set the implementation to "Standard" in all your current Sequences +(ir.sequence) and all new sequences are created as "Standard" by default +instead of "No Gap" implementation. + +What's the problem with "No Gap" Sequence Implementations +========================================================= + +"No Gap" is the default value of sequences in Odoo. However, this kind of +sequences cause more locks and can turn a database slow. + +Taking as example an invoice, if you assign an invoice number to one record, +but it sill not finish the process, this process must end in order to another +invoice could assign a new number and there was no gaps between the invoice +numbers. It seems to be good at first sight. But the problem starts when there +is a chained process. + +Imagine that there is one user that executes a process that produces 100 +invoices and these at the same time produces 100 journal entries that also use +a consecutive (no gap) sequence. And also those invoices are sent to sign with +and external institution (that could take 2 seconds in giving a response +because of internet latency or server load), and maybe they made another +calculations that makes them to take 5 seconds more for each invoice, and all +this is chained to one single transaction. This means that for 8.5 minutes +anybody else could confirm invoices, neither journal entries of the involved +journals. + +Now, think there is 20 users that have to execute a similar process. The +problem turns exponential. If another user comes to make an operation with the +same jornal it will thrown a concurrency failure. + +You can mitigate it if you segment each transaction and don't chain them. It +means, making commit for each invoice or process. It reduces the +probability that there is a concurrency error or a lock wait. However, it still +not solve it completely. + +Why to use Sequences with "Standard" Implementation +=================================================== + +If you use the standard sequence of PosgreSQL, it doesn't lock because at the +moment the request is done, the next sequence number it is changed in an +isolated transaction, and it have not to wait the other transaction to end. +However, if the transaction produces a rollback, this sequence isn't reverted, +it means, it's lost. It may be not not serious because when you cancel or +remove records that number is lost too. + +What this module does +===================== + +To eliminate completely that concurrency/slowness problem, this module changes +all the sequences (ir.sequence) implementation from "No Gap" to "Standard" with +the awareness that it will skip numbers. In the majority of database models +and many users projects there is no problem with that jump occurs. diff --git a/ir_sequence_standard_default/static/description/icon.png b/ir_sequence_standard_default/static/description/icon.png new file mode 100644 index 0000000000000000000000000000000000000000..3a0328b516c4980e8e44cdb63fd945757ddd132d GIT binary patch literal 9455 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 z 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 Xviia!U7SGha1wx#SCgwmn*{w2TRX*I literal 0 HcmV?d00001 diff --git a/ir_sequence_standard_default/static/description/index.html b/ir_sequence_standard_default/static/description/index.html new file mode 100644 index 000000000..a5b322522 --- /dev/null +++ b/ir_sequence_standard_default/static/description/index.html @@ -0,0 +1,455 @@ + + + + + + +IrSequence Standard by Default + + + +
+

IrSequence Standard by Default

+ + +

Beta License: AGPL-3 OCA/server-tools Translate me on Weblate Try me on Runbot

+

Set the implementation to “Standard” in all your current Sequences +(ir.sequence) and all new sequences are created as “Standard” by default +instead of “No Gap” implementation.

+
+

What’s the problem with “No Gap” Sequence Implementations

+

“No Gap” is the default value of sequences in Odoo. However, this kind of +sequences cause more locks and can turn a database slow.

+

Taking as example an invoice, if you assign an invoice number to one record, +but it sill not finish the process, this process must end in order to another +invoice could assign a new number and there was no gaps between the invoice +numbers. It seems to be good at first sight. But the problem starts when there +is a chained process.

+

Imagine that there is one user that executes a process that produces 100 +invoices and these at the same time produces 100 journal entries that also use +a consecutive (no gap) sequence. And also those invoices are sent to sign with +and external institution (that could take 2 seconds in giving a response +because of internet latency or server load), and maybe they made another +calculations that makes them to take 5 seconds more for each invoice, and all +this is chained to one single transaction. This means that for 8.5 minutes +anybody else could confirm invoices, neither journal entries of the involved +journals.

+

Now, think there is 20 users that have to execute a similar process. The +problem turns exponential. If another user comes to make an operation with the +same jornal it will thrown a concurrency failure.

+

You can mitigate it if you segment each transaction and don’t chain them. It +means, making commit for each invoice or process. It reduces the +probability that there is a concurrency error or a lock wait. However, it still +not solve it completely.

+
+
+

Why to use Sequences with “Standard” Implementation

+

If you use the standard sequence of PosgreSQL, it doesn’t lock because at the +moment the request is done, the next sequence number it is changed in an +isolated transaction, and it have not to wait the other transaction to end. +However, if the transaction produces a rollback, this sequence isn’t reverted, +it means, it’s lost. It may be not not serious because when you cancel or +remove records that number is lost too.

+
+
+

What this module does

+

To eliminate completely that concurrency/slowness problem, this module changes +all the sequences (ir.sequence) implementation from “No Gap” to “Standard” with +the awareness that it will skip numbers. In the majority of database models +and many users projects there is no problem with that jump occurs.

+

Table of contents

+
+
+

Bug Tracker

+

Bugs are tracked on GitHub Issues. +In case of trouble, please check there if your issue has already been reported. +If you spotted it first, help us smashing it by providing a detailed and welcomed +feedback.

+

Do not contact contributors directly about support or help with technical issues.

+
+
+

Credits

+
+

Authors

+
    +
  • Vauxoo
  • +
+
+
+

Contributors

+ +
+
+

Maintainers

+

This module is maintained by the OCA.

+Odoo Community Association +

OCA, or the Odoo Community Association, is a nonprofit organization whose +mission is to support the collaborative development of Odoo features and +promote its widespread use.

+

Current maintainers:

+

moylop260 ebirbe

+

This module is part of the OCA/server-tools project on GitHub.

+

You are welcome to contribute. To learn how please visit https://odoo-community.org/page/Contribute.

+
+
+
+ + diff --git a/ir_sequence_standard_default/tests/__init__.py b/ir_sequence_standard_default/tests/__init__.py new file mode 100644 index 000000000..34af958b9 --- /dev/null +++ b/ir_sequence_standard_default/tests/__init__.py @@ -0,0 +1,5 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import test_sequence_standard_default + diff --git a/ir_sequence_standard_default/tests/test_sequence_standard_default.py b/ir_sequence_standard_default/tests/test_sequence_standard_default.py new file mode 100644 index 000000000..eabdac345 --- /dev/null +++ b/ir_sequence_standard_default/tests/test_sequence_standard_default.py @@ -0,0 +1,46 @@ +# Copyright 2016 Vauxoo +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from odoo.tests.common import TransactionCase + + +class TestSequenceStandardDefault(TransactionCase): + + def setUp(self): + + super(TestSequenceStandardDefault, self).setUp() + self.wizard = self.env['sequence.standard.default'].create({}) + self.seq_nogap = self.env['ir.sequence'].create({ + 'name': 'NoGap Sequence', + 'implementation': 'no_gap', + 'use_date_range': False, + 'number_next_actual': 100, + }) + self.seq_nogap_range = self.env['ir.sequence'].create({ + 'name': 'NoGap Sequence with Date Range', + 'implementation': 'no_gap', + 'use_date_range': True, + }) + self.date_range = self.env['ir.sequence.date_range'].create({ + 'sequence_id': self.seq_nogap_range.id, + 'date_from': '2019-01-01', + 'date_to': '2019-12-31', + 'number_next_actual': 200, + }) + self.seq_standard = self.env['ir.sequence'].create({ + 'name': 'Standard Sequence', + 'implementation': 'standard', + 'number_next_actual': 300, + }) + + def test01_nogap_to_std(self): + self.wizard.execute() + + self.assertEqual(self.seq_nogap.implementation, 'standard') + self.assertEqual(self.seq_nogap.number_next_actual, 100) + + self.assertEqual(self.seq_nogap_range.implementation, 'standard') + self.assertEqual(self.date_range.number_next_actual, 200) + + self.assertEqual(self.seq_standard.implementation, 'standard') + self.assertEqual(self.seq_standard.number_next_actual, 300) diff --git a/ir_sequence_standard_default/views/res_config_settings_views.xml b/ir_sequence_standard_default/views/res_config_settings_views.xml new file mode 100644 index 000000000..469cd08f3 --- /dev/null +++ b/ir_sequence_standard_default/views/res_config_settings_views.xml @@ -0,0 +1,31 @@ + + + + + res.config.settings.view.form.inherit.sequence + res.config.settings + + + +
+

Sequences

+
+
+
+
+ Force Standard +
+ Change all your current No Gap sequences to Standard in order to improve performance. +
+
+
+
+
+
+
+ + + + + diff --git a/ir_sequence_standard_default/wizard/__init__.py b/ir_sequence_standard_default/wizard/__init__.py new file mode 100644 index 000000000..8f7dbbbbe --- /dev/null +++ b/ir_sequence_standard_default/wizard/__init__.py @@ -0,0 +1,4 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +from . import sequence_standard_default diff --git a/ir_sequence_standard_default/wizard/sequence_standard_default.py b/ir_sequence_standard_default/wizard/sequence_standard_default.py new file mode 100644 index 000000000..18ce80e57 --- /dev/null +++ b/ir_sequence_standard_default/wizard/sequence_standard_default.py @@ -0,0 +1,42 @@ +# 2019 Vauxoo () +# License AGPL-3.0 or later (http://www.gnu.org/licenses/agpl). + +import logging +from psycopg2.extensions import AsIs + +from odoo import api, models + +_logger = logging.getLogger(__name__) + + +class SequenceStandardDefault(models.TransientModel): + + _name = "sequence.standard.default" + _description = "Wizard to set all sequences to Standard implementation" + + @api.model + def change_all_sequences(self): + sequences = self.env['ir.sequence'].sudo().with_context( + active_test=False).search([('implementation', '=', 'no_gap')]) + _logger.info("Changing sequences to Standard: %s", sequences.ids) + for item in sequences: + seq_name = "ir_sequence_%03d" % (item.id) + self._cr.execute("DROP SEQUENCE IF EXISTS %s", [AsIs(seq_name), ]) + if item.use_date_range: + range_ids = {} + for line in item.date_range_ids: + range_ids[line.id] = line.number_next_actual + seq_name = "ir_sequence_%03d_%03d" % (item.id, line.id) + self._cr.execute( + "DROP SEQUENCE IF EXISTS %s", [AsIs(seq_name), ]) + item.write({'implementation': 'standard'}) + for line in item.date_range_ids: + line.write({'number_next_actual': range_ids[line.id]}) + continue + item.write({'implementation': 'standard'}) + + @api.multi + def execute(self): + self.ensure_one() + self.change_all_sequences() + return self.env.ref('base.ir_sequence_form').read()[0] diff --git a/ir_sequence_standard_default/wizard/sequence_standard_default_views.xml b/ir_sequence_standard_default/wizard/sequence_standard_default_views.xml new file mode 100644 index 000000000..670d456c0 --- /dev/null +++ b/ir_sequence_standard_default/wizard/sequence_standard_default_views.xml @@ -0,0 +1,32 @@ + + + + + Set All Sequences to Standard + sequence.standard.default + +
+

Warning:

+

All sequences in the system will be changed to the Standard + implementation of PostgreSQL. It will improve performance, + but sequence numbers may have gaps between each other.

+

What do you want to do?

+
+
+
+
+
+ + + Set All Sequences to Standard + ir.actions.act_window + sequence.standard.default + form + form + new + + +
+