The registry attributes 'registry_invalidated' and 'cache_invalidated'
are used to flag that the current request has modified the registry or
invalidated the ormcache, respectively. This provides a simple yet
efficient way to signal registry changes or cache invalidations to other
workers.
However, those flags were not meant to be used with multi-threaded
workers. For instance, a thread may signal registry changes that are
actually made by another thread. It can also happen that a thread
changes the registry, which makes another thread crash (like a thread
modifying a dict while another one iterates over it), and the latter
will reset the registry to its original state because it misinterprets
the registry changes as its own changes.
The situation can even get worse, making threads crash in cascade and
eventually leaving the registry in an inconsistent state. When this
happens, the worker is broken and has to be manually restarted.
The fix consists in making those flags thread-specific. This does not
prevent thread crashing because of concurrent changes, but at least it
avoids leaving the worker in a broken state.
closesodoo/odoo#77273
X-original-commit: 28adbfa5a9df9b7754529d45188c0eedeffdf783
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Commit cd12293386 introduced an
optimization in the way that models and their inheritances are loaded,
with this commit we defer the setting of each model class' bases
from the _build_model method to the _prepare_setup method.
This has the advantage of setting any given model class' `__bases__`
attribute only once, but it also means that when _add_manual_models is
called, the __bases__ for ir.model are not yet set (only the default
implementation exists), therefore any module overrides to ir.model do
not take effect when creating the custom models.
This meant that if one creates a custom model with chatter support (i.e.
custom ir.model behaviour implemented in mail) and one restarted the
server, the registry would not properly setup ir.model before creating
the custom model (yielding warnings about tracking and such not being
valid fields) and when creating a record of the custom model, the
registry would crash.
With this commit, ir.model's _prepare_setup is explicitly called before
_add_manual_models to ensure that all overrides to ir.model are taken
into account.
closesodoo/odoo#76325
X-original-commit: f3afb23cdf21f395855771a037c721e977dc93c8
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
Refactor the Environments object into a Transaction object, which is
bound to one cursor, and is no longer shared among several cursors.
The following methods/properties have been changed:
- Environment.envs no longer works (because of the design change);
- Environment.manage() is deprecated (no longer useful);
- Environment.reset() is now an instance method;
- env.clear_upon_failure() is deprecated in favor of cr.savepoint().
closesodoo/odoo#75598
Related: odoo/enterprise#20451
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Co-authored-by: Xavier Dollé <xdo@odoo.com>
Before this commit searched terms were the ones entered by the end-user.
After this commit if the searched term is not found then the search is
performed on a resembling term.
The similarity is obtained from a Levenshtein distance combined with
ratios of common and different letters.
By default the dictionary against which the search term is matched is
based on the content of the search fields containing a word that starts
with the first letter of the search term.
If the `pg_trgm` Postgresql extension is installed the dictionary is
built from matches using the `<%%` operator (similar to the
`word_similarity` function).
Several approaches were benchmarked during development, those results
are available through the task record.
task-2379555
https://github.com/odoo/odoo/pull/65871
Part-of: odoo/odoo#65871
When computing the foreign key name,
`check_foreign_keys` didn't take into account the limit of 63 characters
for constraint names.
Because of this, some constraints were dropped and recreated
over and over while they were correct, during install and upgrades.
For instance, when installing `base`
when adding the foreign key for which the name was computed
`base_partner_merge_automatic_wizard_res_partner_rel_base_partner_merge_automatic_wizard_id_fkey`
Postgresql created the constraint under the name
`base_partner_merge_automatic__base_partner_merge_automatic_fkey`
and therefore, as the name did not match,
the constraint was dropped and re-created.
closesodoo/odoo#72234
X-original-commit: 43a4738ebf8a74a389b99f8f58330b3044beaa0c
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
This makes the union of many dicts into a single dict.
On a registry with 296 modules, this saves 300 kilobytes of memory,
which is about 3% of the registry's memory footprint.
When a registry is loading, if a custom field cannot be set up, it will
be removed from the dependencies of the field 'display_name', which do
not exist yet on the registry. This patch makes sure that the dict
registry.field_depends always exists, even as an empty dict.
closesodoo/odoo#70373
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
The attributes field.depends and field.depends_context are problematic
for sharing fields across registries, because they depend on the model's
registry class, which may vary from one registry to another. In order
to make computed fields shareable, we have to move those values away
from fields.
For the same reason, field.recursive should not be inferred, because its
value may depend on the registry, although it is generally not the case.
Moreover, the flag recursive=True is set on a field when field triggers
are determined (on the registry). A compute method may be called before
the flag is set (if no update has been done yet), and that can lead to
incorrect computations.
This happened in test TestUsers2.test_reified_groups in module 'base'.
The user groups view was apparently determined without the flag being
set, and the view depends on the recursive field 'trans_implied_ids',
which was not correctly computed.
We thus force developers to be explicit about recursive computed fields.
The code now logs a warning when the flag is not set up properly.
CRM install query count can vary from one execution to another, leading
to difficulties when analysing performances evolution.
The main reason for this is that some compute methods were called in
different order. Even if compute order shouldn't have any effect on the
final result, making it well defined will help finding other causes of
non-determinism.
The initial observation was that sorting Environment.fields_to_compute
leads to a fixed number of query when installing crm.
The main cause of non-determinisim is the usage of `set` impacting
Field.compute_value and BaseModel._modified_triggers.
Transforming all these `set` to `OrderedSet` solves the problem.
The query count is now deterministic when installing a database from
scratch, but not when updating a database with -i crm.
OrderedSet is also slightly optimised by using a dict instead of an
closesodoo/odoo#68692
Ordereddict: dict order is deterministic since python3.6
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
When an index has name 'tablename_fieldname_index', this index is
dropped if the field has index=False. This lead to dropping a
user-created index or dropping/recreating the index when index=True is
set in a dependent module. Some info is logged instead.
closesodoo/odoo#67602
X-original-commit: 6a87318df296a11e3300723ca0c8b49c0dcf5fa7
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
When table name is long enough, the foreign key constraint name computed
by odoo and the one by PostgreSQL are different, for the same table,
column and definition, are different. As an example,
base_partner_merge_automatic_wizard_res_partner_rel(partner_id) foreign
key is named
base_partner_merge_automatic_wizard_res_partner_rel_res_partner_id_fkey
in Odoo while it's
base_partner_merge_automatic_wizard_res_par_res_partner_id_fkey in
PostgreSQL. This difference trigger a useless foreign key drop/create.
closesodoo/odoo#67601
X-original-commit: 353b415c74da057d5e81cce4d309bebb5f0f2927
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This patch complements the previous one by ensuring that any
`cache_invalidated=True` flag inherited from the master process
(pre-fork mode) cannot trigger a cache clear.
This could occur when the first request is served, because the flag was
never clear in the master process, which never server any request.
At the end of `check_signaling()`, the local cache has either been
cleared because a (real) increment of the cache sequence was detected,
or it is considered still valid. The final state of the
`cache_invalidated` flag should reflect this, by being `False`.
closesodoo/odoo#65346
X-original-commit: 3585c2c38955ece4292da77de7173fb31a6992ba
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
During loading, the registry clears all `ormcache` data multiple
times, in order to ensure consistency with the newly loaded module
data.
Since 083c70bbb6, this was done by
calling `self.clear_caches()`, with the side-effect
of signalling to all other worker processes that the cache
*needs* to be invalidated, which is actually untrue.
If the other workers have any reason to reload their own registries,
they will also clear their own cache in the process - there is no
need to forcefully invalidate it globally.
One could think that combining the pre-fork mode with the `-d <db>`
parameter would mitigate this issue, by making all workers inherit from
a fully loaded registry, In reality it doesn't work, because they also
inherit from the `cache_invalidated=True` flag, that was never cleared
in the master process. So despite having a fully loaded registry, the
newly forked workers will signal a cache invalidation upon serving
their first request.
Further, in a multi-tenant setup with large numbers of databases,
registries may be recycled and loaded much more frequently than
new workers are starting, due to the limited registry LRU, amplifying
this effect a bit.
~~
This patch directly clears the cache LRU without going through
`clear_cache()`, avoiding setting the `cache_invalidated` flag of the
registry, and thus not signalling to other workers.
This is similar to what was being done before 083c70bbb6,
where the LRU was dropped like all other lazy properties.
X-original-commit: 87aef4e3a36d92462454f51960abf7215c5ab7f1
Currently in 13.0 when creating a new model through studio and convert
the x_name field to a computed fields with a dependency set on a
custom field from a native model, user get a Key_error when upgrading
or installing a new module
due to the custom field with an invalid depends raise error through a
transitive dependency.
The loading of the registry completely fails,
because the loading of the field custom_field raises a `KeyError` exception
in `def transitive_dependencies` @ `dependencies[field]`
it happens here because the custom_field was skipped at
`dependencies[field] = set(field.resolve_depends(model))`
task - 2366502
closesodoo/odoo#61663
X-original-commit: 92f6908bae4a6678f76a3ce9e29ac3907803ceb2
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Before this patch, adding a field on a custom model discards all
automated actions on that model. The explanation is relatively simple.
When models are set up in the registry, the classes of custom models are
dropped then recreated. Given that automated actions are implemented as
monkey-patches on model classes, the setup of models simply loses those
monkey-patches, which explains why they stop working on custom models.
The fix introduces an `_unregister_hook()` method, that is expected to
clean up what has been done in `_register_hook()`. When the registry is
ready (i.e., not being loaded), the setup of models first invokes
`_unregister_hook()` on models, proceeds with the setup, and finally
invokes `_register_hook()` to reinstall the hooks.
OPW 2362308
closesodoo/odoo#60833
X-original-commit: 67152bf82da2674179297d32e4cec9dd534fa0c9
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
By adding a parameter `_table_query` on the Model, we can now have views
that depend on the context. The query is used instead of the table name
in ORM operations. This allows to pre-compute some values to improve
performance, instead of storing context values in the database.
Co-authored-by: william-andre <wan@odoo.com>
Co-authored-by: rco-odoo <rco@odoo.com>
That's a not-very-useful subset of OdooTestResult, so:
* make results merge-able (aka add ability to update a result with the
contents of another)
* remove support for test data files, and transmission of the
assertion report thing through the data-files loading
* replace "legitimate" uses of assertion report by test result
* have run_unit_tests manipulate and return a result instead of weird
flags & ternaries
Before this, invalidations to the UID cache is not synchronised
between workers because it's an ad-hoc solution (so a user changing
their password or an admin disabling a user would only lock out an
attacker currently using the API of one of possibly several
workers). Shift the entire thing to ormcache which already has proper
support for synchronising cache invalidation between workers.
Also simplify the cache invalidation mess in Users.write because the
caches have been unified into a single registry-level LRU, so the
half-dozen cache clears on specific ormcached methods & models is
pretty much the same as repeatedly calling clear_caches on the current
model.
**However** registry.cache is trivially accessible from server actions
and safe_eval as long as they provide access to a model (through
`model.pool.cache`). Which is common, and an issue given we're very
much putting sensible data in there.
Fix this by renaming `Registry.cache` to `Registry.__cache`, this
requires few editions and mangled names are not accessible from
safe_eval contexts.
The alternative would have been to add more bespoke handling of the
uid cache to hook it into the cache invalidation propagation
machinery.
After discussion with (@)odony, fixing LRU access and using that seems
cleaner and less error-prone.
Note on lazy_property
=====================
Make Registry.cache / Registry.__cache into a regular attribute: the
overhead of the LRU is not that high (compared to that of the registry
itself), it's rare that we *don't* need it, and it's assumed to be a
persisted attribute (it's not just a cache) so making it a normal
attribute seems fine; and lazy_property doesn't work for mangled
names: the name of the property is mangled using the name of the
definition class, but the name of the symbol (fget) is not mangled so
lazy_property would set the __cache attribute but then Python would
lookup _Registry__cache, creating a new cache every access.
And we can't (always) mangle things correctly on `__get__(obj,
owner)`: `owner` is just `type(obj)`, meaning in the case of
inheritance the type we get is the type through which the property is
accessed rather than the one it's defined on. So it would work in the
cases where no inheritance is involved (such as Registry.__cache) but
not in general (lest we want to play around walking the MRO ourselves
to find the definition source, which doesn't seem worth it).
lazy_property *could* be made to work properly on Python 3.6+: the
descriptor protocol gains `__set_name__(name, owner)`, which is called
with the properly mangled name — and with the definition class to boot
(though there might still be issues when overriding lazy properties as
the override will be mangled & named differently... or maybe that's a
feature?). However we're still supporting 3.5 at this point, AFAIK, so
that's not an option. Plus it feels unnecessary / not very useful.
However add an assertion to `lazy_property` so it signals when we try
to use it on a mangled method (as otherwise it kinda sorta work in the
sense that the property / object is accessible but is in effect a
slower way to write a regular property).
This is a followup of commit bc2bb5e03c2b32d4ee1b0597ea5889c17d2b0e0e
When a module is updated, a constraint application may (temporarily)
fail because the existing data does not respect the constraint, this is
OK and can be fixed through hooks/migration scripts and was handled by
the aforementioned commit.
However when updating multiple modules, it is possible that an
inheriting module will try to re-apply the failed constraint and
succeed, if that is the case, when processing the `post_constraints` an
already-existing constraint will be applied and raise an error.
To fix this, a check is made before trying to apply the constraint, to
verify that it is not already in _constraint_queue, if it is not, then
we may attempt to apply it, if it is in the queue, then we may safely
ignore it as it will be applied further down the registry cycle.
closesodoo/odoo#55725
X-original-commit: 5225b9ce5178302af05b63029fb184e27b781815
Signed-off-by: Adrian Torres (adt) <adt@odoo.com>
This is related to
826c86e9ab31963e410887a30326f45bcfadf5ea
The case is the same,
a custom field with an invalid depends,
except that this time its through a transitive dependency.
e.g.
custom_field_2 depends on custom_field_1
custom_field_1 depends on unexisting_field
The loading of the registry completely fails,
because the loading of the field `custom_field_2` raises a
`KeyError` exception in
`def transitive_dependencies` @ `dependencies[field]`
because the `custom_field_1` was skipped @ line
`dependencies[field] = set(field.resolve_depends(model))`
Landing in a state where the server can no longer start at all,
and the user can't therefore solve its custom field himself
to repair the situation.
closesodoo/odoo#51057
X-original-commit: 7b642884cc4d643a5a998b4639bf26b4e81cc46e
Signed-off-by: Denis Ledoux (dle) <dle@odoo.com>
Iteration methods on LRU were removed because they were not
thread-safe and it's not clear that making them thread-safe is the
correct thing to do, so not providing them seems saner.
I thought I'd looked for usages of the LRU but apparently didn't look
hard enough as I missed that it's used by the cron workers (apparently
using the threaded server we only run crons for dbs currently living
in the registry cache, the more you know).
Convert these to iterating on the LRU's internal mapping, and also
don't iterate on the LRU to clear its entries one by one when we can
just clear the entire thing safely, although Registry.delete_all
really seems completely unused.
closesodoo/odoo#49023
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
This greatly reduces the number of queries to add foreign keys (notably
for many2one fields).
This saves 6.5% of the total installation time.
X-original-commit: 13a2666b4da09fc0ec7608a974dadde45f76fd7a
Reduce the number of queries to create and drop indexes.
This saves 1.5% of the total installation time.
X-original-commit: 0e1e480da9d971575feba64038c4fa518ebe102b
This is necessary in order to create models on-the-fly within tests and
to test improper Model / Field creation: registry.reset_changes will
only perform the reset of the registry if it is invalidated, however if
the setup of models crashes before it is invalidated (as is the case of
a test), the reset_changes will not be triggered and thus the registry
will be left dirty for subsequent tests.
* from collections import <ABC> is deprecated, unclear why the
deprecation warning didn't appear before (possibly only appears in
3.7/3.8?) either way `collections.abc` should be 3.3+ so switch
everything to it.
* add some more ignores on third-party packages deprecation
warnings (meh)
* while at it, mitigate generation of non-breaking space on some
versions of Babel (in the french locale used by our tests anyway)
closesodoo/odoo#47581
Related: odoo/enterprise#9214
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Before this the `--unaccent` flag does double duty to specify whether
to create new databases with the extension *and* to try to use the
corresponding function.
The latter is further gated on the function existing at all in the
database.
Given postgresql does not have unaccent installed by default it seems
only the latter is really useful and we can ignore the flag to decide
whether to enable unaccent features, if the extension is installed
consider that it should be enabled and move on.
Merge this in master rather than previous versions as it can change
things like index access / use.
closesodoo/odoo#47377
Signed-off-by: Xavier Morel (xmo) <xmo@odoo.com>
Sometimes, constraints are not delayed during a module upgrade: the
module is 'to upgrade' but in 'init' mode :-/
Fix this by relying on the module's state only.
closesodoo/odoo#45179
X-original-commit: 878b6538961a9b6a5fe1c6ac68d4ff39391abcdf
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
In some case, a pre-migration script calls `xml_import.parse` to force
reload a no-update data in pre-script. It is possible that fields are
marked to recompute in the process. The problem is that the reference to
the field added in `env.all.tocompute` won't be the same as the
reference of the same field after calling `registry.setup_models()`,
leading to an infinite loop while recomputing this field, since
`fields.__get__` wont find `self` in `env.all.tocompute`.
This problem was discovered when trying to migrate a database with all
modules installed (no demo data) from 12.0 to 13.0 (for commit
references: http://runbot.odoo.com/runbot/build/1176576 with database
comming from http://runbot.odoo.com/runbot/build/1171714).
This commit adds a check before executing `registry.setup_models()` in
order to log when some fields to compute remain before breaking fields
references, and adds a `flush()` after pre-scripts to fix the current
issue.
X-original-commit: 41b9d810066774736c4077bba1dc9c9fba004f48
When adding a custom field, the ORM also adds it to all the inherits'ed
models, but with the state `base`, because those inherited fields are
automatic (created by the ORM). However, dependencies are enforced for
`base` fields, while they can be ignored for `manual` ones. This is a
problem when a custom field is fucked up: its inherited fields will make
the registry crash.
We fix the issue by not enforcing dependency check on fields inherits'ed
from custom fields.
opw-2191114
closesodoo/odoo#45024
X-original-commit: 2db0787dc9e8717200aaf1d71ac64df1c17f4143
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
When removing a custom model, it remained listed in the base classes
(normally `base` and also possibly a list of mixins; e.g. `mail.thread`
or `mail.activity.mixin`) list of inheriting classes, possibly causing a
crash when trying to reload the registry.
This commit ensures that any custom model is removed from its parent
class `_inherit_children` set; it will be re-added automatically during
the call to `_build_model` if the custom model still exists.
Co-Authored-By: Raphaël Collet <rco@odoo.com>
When a call to init_models() fails, the post-init queue still contains
callables that refer to a soon-to-be-closed cursor. If one calls
init_models() in another request, the post-init process will inevitably
fail because it refers to closed cursors.
closesodoo/odoo#40379
X-original-commit: 33f87ffebaa1cb38e3ce8ce44c8b8b538b49e5b9
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
Ignore exceptions when resolving dependencies in that case.
This reimplements a behavior from former versions.
closesodoo/odoo#40300
X-original-commit: 826c86e9ab31963e410887a30326f45bcfadf5ea
Signed-off-by: Christophe Simonis <chs@odoo.com>
The queries made by the method `_is_an_ordinary_table` represent about
8% of the time to do a full Odoo installation. Use a cached query for
all tables on the registry to reduce that time to some negligible
amount.
closesodoo/odoo#39262
Signed-off-by: Xavier Dollé (xdo) <xdo@odoo.com>
This prevents a bunch of queries that are useless when creating a
record. Indeed, right after a record has been created, no other record
has a many2one reference to it. In other words, inversing a many2one
field from the record just created always gives an empty recordset.
Those useless inversions generate about a dozen queries when creating a
`res.partner`, for instance.
This saves queries, but not much time.
closesodoo/odoo#36566
Signed-off-by: Raphael Collet (rco) <rco@openerp.com>
This branch is the combination of several optimizations in the ORM:
* store field values once in the cache: the cache reflects more
faithfully the database, only fields that explicitly depend on the
context have an extra indirection in the cache;
* delay recomputations by default: use method `recompute` to explicitly
flush out pending recomputations;
* delay updates in method `write`: updates are stored in a data
structure that can be flushed efficiently to the database with method
`flush` (which also flush out recomputations);
* make method `modified` take advantage of inverse fields to inverse
dependencies;
* filter records by evaluating a domain on records in Python;
* a computed field with `readonly=False` behaves like a normal field
with an onchange method;
* computed fields are computed in superuser mode by default.
Work done by Toufik Ben Jaa, Raphael Collet, Denis Ledoux and Fabien
Pinckaers.
closesodoo/odoo#35659
Signed-off-by: Denis Ledoux <beledouxdenis@users.noreply.github.com>
Store the SQL constraint message directly in the field `message` of the
corresponding `ir.model.constraint` record, and manage translations from
there. Those records are given an XML id in order to be tracked in PO
files. The translation type 'sql_constraint` is removed.
This problem appears when the module l10n_be_hr_payroll_fleet is installed with the
dynamic report for employees (enterprise module hr_contract_reports).
This module inherits from hr.contract and will create and modify some fields.
By modifying contract's table, PostgreSQL will drop the view from
hr_contract_employee_report. At the end of the installation, PostgreSQL will
check if tables exist, it isn't the case for the view from
hr_contract_employee_report, so it will recreate it.
It's the normal behavior.
But when a table is missing, a warning is logged and create problem with
Runbot. For this reason, it's better to log an Info and not a Warning message.
Validated with @rco
This allows a model to have several fields using the same relation on purpose,
for instance to show the related items filtered by domains.
Also adapt the code to handle multiple many2many inverses.
closesodoo/odoo#30338