Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Further performance improvements for sample creation #2376

Draft
wants to merge 11 commits into
base: 2.x
Choose a base branch
from
1 change: 1 addition & 0 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ Changelog
2.5.0 (unreleased)
------------------

- #2376 Further performance improvements for sample creation
- #2382 Fix missing fields in client edit mode and listing
- #2378 Reactivate auditlog catalog mappings
- #2377 Fix imports for moved idserver module
Expand Down
29 changes: 17 additions & 12 deletions src/bika/lims/utils/analysisrequest.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@
from Products.CMFPlone.utils import _createObjectByType
from Products.CMFPlone.utils import safe_unicode
from senaite.core.catalog import SETUP_CATALOG
from senaite.core.idserver import generateUniqueId
from senaite.core.idserver import renameAfterCreation
from senaite.core.permissions.sample import can_receive
from senaite.core.workflow import ANALYSIS_WORKFLOW
Expand Down Expand Up @@ -83,21 +84,23 @@ def create_analysisrequest(client, request, values, analyses=None,
service_uids = to_services_uids(values=values, services=analyses)

# Remove the Analyses from values. We will add them manually
values.update({"Analyses": []})
values.pop("Analyses", None)

# Remove the specificaton to set it *after* the analyses have been added
specification = values.pop("Specification", None)

# Create the Analysis Request and submit the form
# create a new sample with a temporary ID
ar = _createObjectByType("AnalysisRequest", client, tmpID())
# mark the sample as temporary to avoid indexing
api.mark_temporary(ar)

# Set the schema fields using `processForm` to convert the raw form values
# by the widget into the right field value!
#
# NOTE: We call here `_processForm` (with underscore) to manually unmark
# the creation flag and trigger the `ObjectInitializedEvent`, which
# is used for snapshot creation.
ar._processForm(REQUEST=request, values=values)

# Set the analyses manually
# Explicitly set the analyses with the ARAnalysesField
ar.setAnalyses(service_uids, prices=prices, specs=results_ranges)

# Explicitly set the specification to the sample
Expand Down Expand Up @@ -147,14 +150,16 @@ def create_analysisrequest(client, request, values, analyses=None,
changeWorkflowState(ar, SAMPLE_WORKFLOW, "sample_due",
action="no_sampling_workflow")

renameAfterCreation(ar)
# AT only
# unmark creation flag
ar.unmarkCreationFlag()
# unmark the sample as temporary
api.unmark_temporary(ar)
# explicit reindexing after sample finalization
reindex(ar)
# notify object initialization (also creates a snapshot)

# generate a new unique ID
new_id = generateUniqueId(ar)

# manually rename the sample (this will also reindex the sample analyses)
client.manage_renameObject(ar.id, new_id)

# notify object initialization (snapshot creation)
event.notify(ObjectInitializedEvent(ar))

# If rejection reasons have been set, reject the sample automatically
Expand Down
56 changes: 36 additions & 20 deletions src/senaite/core/patches/catalog.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,14 +18,14 @@
# Copyright 2018-2023 by it's authors.
# Some rights reserved, see README and LICENSE.

import transaction
from bika.lims import api
from senaite.core.interfaces import IMultiCatalogBehavior
from plone.indexer.interfaces import IIndexableObject
from Products.ZCatalog.ZCatalog import ZCatalog
from Products.ZCatalog.Catalog import CatalogError
from senaite.core import logger
from senaite.core.catalog import AUDITLOG_CATALOG
from senaite.core.interfaces import IMultiCatalogBehavior
from senaite.core.setuphandlers import CATALOG_MAPPINGS
from zope.component import queryMultiAdapter

PORTAL_CATALOG = "portal_catalog"
CATALOG_MAP = dict(CATALOG_MAPPINGS)
Expand All @@ -38,32 +38,48 @@ def is_auditlog_enabled():
return setup.getEnableGlobalAuditlog()


def catalog_object(self, object, uid=None, idxs=None,
update_metadata=1, pghandler=None):
def catalog_object(self, obj, uid=None, idxs=None, update_metadata=1,
pghandler=None):

instance = obj

# get the unwrapped instance object
if IIndexableObject.providedBy(obj):
instance = obj._getWrappedObject()

# Never catalog temporary objects
if api.is_temporary(object):
if api.is_temporary(instance):
return

# skip indexing auditlog catalog if disabled
if self.id == AUDITLOG_CATALOG:
if not is_auditlog_enabled():
return

if idxs is None:
idxs = []
self._increment_counter()

w = object
if not IIndexableObject.providedBy(object):
# This is the CMF 2.2 compatible approach, which should be used
# going forward
wrapper = queryMultiAdapter((object, self), IIndexableObject)
if wrapper is not None:
w = wrapper

ZCatalog.catalog_object(self, w, uid, idxs,
update_metadata, pghandler=pghandler)
if uid is None:
try:
uid = obj.getPhysicalPath
except AttributeError:
raise CatalogError(
"A cataloged object must support the 'getPhysicalPath' "
"method if no unique id is provided when cataloging")
else:
uid = '/'.join(uid())
elif not isinstance(uid, str):
raise CatalogError('The object unique id must be a string.')

self._catalog.catalogObject(obj, uid, None, idxs,
update_metadata=update_metadata)
# None passed in to catalogObject as third argument indicates
# that we shouldn't try to commit subtransactions within any
# indexing code. We throw away the result of the call to
# catalogObject (which is a word count), because it's
# worthless to us here.

if self.maintain_zodb_cache():
transaction.savepoint(optimistic=True)
if pghandler:
pghandler.info('committing subtransaction')


def in_portal_catalog(obj):
Expand Down
2 changes: 1 addition & 1 deletion src/senaite/core/patches/configure.zcml
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@

<monkey:patch
description=""
class="Products.CMFPlone.CatalogTool.CatalogTool"
class="Products.ZCatalog.ZCatalog.ZCatalog"
original="catalog_object"
replacement=".catalog.catalog_object"
/>
Expand Down
Loading