Skip to main content

Historical state of objects stored in the ZODB

Project description

Utilities to access the historical state of objects stored in a (history aware) ZODB (Zope Object DataBase). They can be useful to find out what happened to objects in the past and to restore accidentally deleted or modified objects.

I have used them recently to analyse a case where colleagues reported about mysteriously lost objects. It turned out that the objects have not been lost at all but only became unindexed.

This version is tested against ZODB 3.4. It will not work with ZODB 3.2. It may (or may not) work with more recent ZODB versions. Beside ZODB, this version requires Zope’s DateTime package.

API

Currently, there are two utilities: getHistory(obj, first=0, last=20) and getObjectAt(obj, time).

time can be a Zope DateTime instance, a float in seconds since epoch or a serial/transaction id.

Usage example

In the example below, the ZODB contains a folder f. Let’s have a look at its history.

>>> from dm.historical import getHistory, getObjectAt
>>> from pprint import pprint as pp
>>> h = getHistory(f)
>>> pp(h)
[{'description': '',
  'obj': <Folder at /f>,
  'size': 157L,
  'tid': '\x03r\xc8\x1b\xf3hhU',
  'time': DateTime('2008/01/01 09:59:57.049 GMT+1'),
  'user_name': '',
  'version': ''},
 {'description': '',
  'obj': <Folder at /f>,
  'size': 124L,
  'tid': '\x03r\xc8\x1bX\x0e\xfb\xcc',
  'time': DateTime('2008/01/01 09:59:20.639 GMT+1'),
  'user_name': '',
  'version': ''},
 {'description': '',
  'obj': <Folder at /f>,
  'size': 48L,
  'tid': '\x03r\xc8\x15\x1c\x9f\xb03',
  'time': DateTime('2008/01/01 09:53:06.709 GMT+1'),
  'user_name': '',
  'version': ''}]

This tells us that the ZODB knows about 3 transactions affecting f. We can access its state after the first transaction.

>>> f1 = h[-1]['obj']
>>> f1.objectIds()
[]

f was empty at that time. Let’s see how f was changed by the other transactions:

>>> for hr in h:
...   print hr['time'].strftime('%H:%M:%S'), hr['obj'].objectIds()
...
09:59:57 ['x', 'y']
09:59:20 ['x']
09:53:06 []

This tells us that the second transaction added x and the third transaction y.

We can control which history records are retrieved with the optional parameters first and last.

>>> pp(getHistory(f,last=1))
[{'description': '',
  'obj': <Folder at /f>,
  'size': 157L,
  'tid': '\x03r\xc8\x1b\xf3hhU',
  'time': DateTime('2008/01/01 09:59:57.049 GMT+1'),
  'user_name': '',
  'version': ''}]
>>> pp(getHistory(f,first=2))
[{'description': '',
  'obj': <Folder at /f>,
  'size': 48L,
  'tid': '\x03r\xc8\x15\x1c\x9f\xb03',
  'time': DateTime('2008/01/01 09:53:06.709 GMT+1'),
  'user_name': '',
  'version': ''}]

getObjectAt can be used to retrieve the historical state at a given time. Say, we want to learn how f was at 9:55. The most easy way to specify a time is via a DateTime.

>>> from DateTime import DateTime
>>> dt=DateTime(2008,1,1,9,55)
>>> dt
DateTime('2008/01/01 09:55:00 GMT+1')
>>> getObjectAt(f, dt).objectIds()
[]

When we request the state beyond the ZODB’s maintained history, we get a POSKeyError.

>>> getObjectAt(f, DateTime(2008,1,1,9,50))
Traceback (most recent call last):
  ...
ZODB.POSException.POSKeyError: ('\x00\x00\x00\x00\x00j\x82\xd3', '\x03r\xc8\x12\x00\x00\x00\x00')

The time can also be specified via a float in the unit seconds since epoch or via a serial/tid. However, these will be used rarely.

>>> ts=dt.timeTime()
>>> ts
1199177700.0
>>> getObjectAt(f, ts).objectIds()
[]
>>> getObjectAt(f, '\x03r\xc8\x15\x1c\x9f\xb03').objectIds()
[]

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dm.historical-1.0.1.tar.gz (7.0 kB view details)

Uploaded Source

File details

Details for the file dm.historical-1.0.1.tar.gz.

File metadata

  • Download URL: dm.historical-1.0.1.tar.gz
  • Upload date:
  • Size: 7.0 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No

File hashes

Hashes for dm.historical-1.0.1.tar.gz
Algorithm Hash digest
SHA256 6dc124a17f9c289a8ace614714c0ddd149e02f18a817096ec31e9a4691f7d8f8
MD5 44f06658c2b73275f2f54535b14d12e0
BLAKE2b-256 dca79aefbddde8b40ead484ccab5a8f7983098e75574646acba14c2f5da2b969

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page