Comments (3)
Relates to #853
from viur-core.
I did a bit of research. The problem with the context managers is that you can't execute the code to the context repeatedly. However, this may be necessary because the transaction fails.
An example:
def tnx(key):
obj = db.Get(key)
obj["count"]+=1
db.Put(obj)
This function runs in a transaction and the transaction fails with a CollisionError
, then the viur-datastore waits 2 seconds and then tries again and executes the function again so that we can count accurately.
But when we have code like:
db.Transaction():
obj = db.Get(key)
obj["count"]+=1
db.Put(obj)
And here the the transaction fails we can not rerun the fuction.
If there is a solution to this problem, it would be nice, but I haven't found one.
from viur-core.
Hello @ArneGudermann, thanks for taking a closer look on this.
IMHO this could be achieved by modifying and/or modularization of code in viur-datastore, around here: https://github.com/viur-framework/viur-datastore/blob/master/src/viur/datastore/transport.pyx#L806
There is a beginTransaction and a commit, which must be turned into the ContextManager object.
Nevertheless, I don't want to heavily change viur-datastore for features in viur-core, as we still plan to integrate other database adapters in far future.
As an alternative for this issue, this is my most-current version of the set_status
function I'm using throughout several projects:
"""
This module contains some project-specific helper functions.
"""
import logging
import time
from viur.core import db, errors
def set_status(key, values=None, check=None, func=None, skel=None, retry=3, update_relations=False):
"""
Universal function to set a status of an db.Entity or Skeleton within a transaction.
:param key: Entity/skeleton key to change
:param values: A dict of key-values to update on the entry
:param check: An optional dict of key-values to check on the entry before
:param func: A function that is called inside the transaction
:param skel: Use assigned skeleton instead of low-level DB-API
:param retry: On BadRequestError, retry for this amount of times.
:param update_relations: Instruct ViUR to update relations (normally not required)
If the function does not raise an Exception, all went well.
It returns either the assigned skel, or the db.Entity on success.
"""
if callable(values):
assert not func, "'values' is a callable, but func is also set. Either set values or func in this case."
func = values
values = None
else:
assert isinstance(values, dict) or values is None, "'values' has to be a dict when set"
def transaction():
if skel:
if not skel.fromDB(key):
raise errors.NotFound()
obj = skel
else:
obj = db.Get(key)
if check:
if callable(check):
assert check(obj)
else:
assert isinstance(check, dict), "'check' has to be a dict, you diggi!"
for bone, value in check.items():
assert obj[bone] == value, "%r contains %r, expecting %r" % (bone, obj[bone], value)
if values:
for bone, value in values.items():
if bone[0] == "+":
obj[bone[1:]] += value
elif bone[0] == "-":
obj[bone[1:]] -= value
else:
obj[bone] = value
if func:
assert callable(func)
func(obj)
if skel:
assert skel.toDB(update_relations=update_relations)
else:
db.Put(obj)
return obj
if not retry:
retry = 1
for i in range(retry):
try:
return db.RunInTransaction(transaction)
except db.Error as e:
logging.exception(e)
logging.debug(f"Retry {i}")
time.sleep(i)
except Exception:
raise
raise errors.InternalServerError()
Integrated and attached to Skeleton
, this could also be executed like skel.transact({"+count", 1})
or skel.transact(callback_func)
, which is much nicer and shorter than using db.RunInTransaction
.
from viur-core.
Related Issues (20)
- Set `admin_info` of `Translation` module HOT 3
- Add type for query order
- compute doesn't work in a `RelationalBone` HOT 1
- Implement `UidBone`
- Implement `has_changed` flag in bones and Skeletons HOT 2
- Refactor `User`: `authenticationProviders`, `secondFactorProviders` and `validAuthenticationMethods`
- refactor: Move special system arguments for `CallDeferred` in `mkdefered`'s signature
- compute not working with keybones. HOT 3
- Subclass `Session` from `db.Entity` to inherit all dict-features HOT 1
- RelationalBone `defaultValue` not working HOT 2
- `PhoneBone` required HOT 1
- Arguments passed to an `@exposed` method as positional and keyword are not refused
- Add abstract / base class for all renderers
- a Simple Redirect Handler for mapping urls
- viur-core >= 3.6: How to make parts of the config available to the client?
- Save hash of files in `FileSkel`
- `BooleanBone`'s `defaultValue` cannot be a `callable`
- Core cleans non breaking spaces from Text Bone Input HOT 1
- Extend `MultipleConstraints` to accept for a sort method HOT 1
- Fix xml renderer HOT 1
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from viur-core.