Commit 129afa67 authored by Kirill Smelkov's avatar Kirill Smelkov

zodbcommit: Provide full context when reporting errors

In the previous patch we taught object copy handler to report more
details, but it was still incomplete - the error was missing details
about which operation was run - commit, or restore of particular
transaction.

Noting that it can be also noted that other errors reported from that
function lack such context.

-> So fix it universally, at least for zodbcommit for now: set top-level
runctx to topic of what we are doing, and use that runctx when
generating errors. Runctx describes what we are running, and could be
also later used for logging and tracing. That's why it is called runctx
instead of just errctx for "error context".

TODO currently it is only exceptions that we explicitly raise which get
the context. If an exception is raised by something that we call - the
context won't be added. It would be good to later rework error handling
and append such context for any raised error. Defer and
https://lab.nexedi.com/kirr/go123/blob/863c4602/xerr/__init__.py has
something preliminary for this.

The particular error when restoring a missing object copy becomes

    ValueError: /tmp/demo002868462/δ0285cbac75555580/δ.fs: restore 0285cbacb70a3db3 @0285cbacb258bf66: object 0000000000000003: copy from @0285cbac70a3d733: no data

instead of older

    ValueError: /tmp/demo358030847/δ0285cbac75555580/δ.fs: object 0000000000000003: copy from @0285cbac70a3d733: no data

/reviewed-by @jerome
/reviewed-on nexedi/zodbtools!20
parent fa00c283
......@@ -77,8 +77,10 @@ def zodbcommit(stor, at, txn):
# of this is NEO. We anyway need to be able to specify which transaction ID
# we need to restore transaction with.
stor.tpc_begin(txn, tid=txn.tid)
runctx = "%s: restore %s @%s" % (stor.getName(), ashex(txn.tid), ashex(at))
else:
stor.tpc_begin(txn)
runctx = "%s: commit @%s" % (stor.getName(), ashex(at))
def _():
def current_serial(oid):
......@@ -94,7 +96,7 @@ def zodbcommit(stor, at, txn):
xdata = None
if xdata is None:
raise ValueError("%s: object %s: copy from @%s: no data" %
(stor.getName(), ashex(obj.oid), ashex(obj.copy_from)))
(runctx, ashex(obj.oid), ashex(obj.copy_from)))
data, _, _ = xdata
elif isinstance(obj, zodbdump.ObjectDelete):
......@@ -103,12 +105,12 @@ def zodbcommit(stor, at, txn):
elif isinstance(obj, zodbdump.ObjectData):
if isinstance(obj.data, zodbdump.HashOnly):
raise ValueError('cannot commit transaction with hashonly object')
raise ValueError('%s: cannot commit transaction with hashonly object' % runctx)
data = obj.data
else:
panic('invalid object record: %r' % (obj,))
panic('%s: invalid object record: %r' % (runctx, obj,))
# we have the data -> restore/store the object.
# if it will be ConflictError - we just fail and let the caller retry.
......@@ -140,8 +142,7 @@ def zodbcommit(stor, at, txn):
assert len(_) == 1
tid = _[0]
if want_restore and (tid != txn.tid):
panic('restore: restored transaction has tid=%s, but requested was tid=%s' %
(ashex(tid), ashex(txn.tid)))
panic('%s: restored transaction has different tid=%s' % (runctx, ashex(tid)))
return tid
# _serial_at returns oid's serial as of @at database state.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment