Skip to content

fetch_schema leaves the page cache enabled when given more than one schema title #176

Description

@LukasGold

Problem

OSW.fetch_schema enables the page cache and fails to restore the previous
state when it is called with more than one schema title. The cache stays enabled
for the rest of the process. A later get_page can then return a revision from
before a write that happened in between.

Mechanism

fetch_schema processes the titles one at a time. Each invocation does this at
https://github.com/OpenSemanticLab/osw-python/blob/9aa6322/src/osw/core.py#L598:

site_cache_state = self.site.get_cache_enabled()
self.site.enable_cache()

site_cache_state is a local variable of that invocation. The restore is
guarded by final at
https://github.com/OpenSemanticLab/osw-python/blob/9aa6322/src/osw/core.py#L1057:

if fetchSchemaParam.final:
    importlib.reload(model)
    if not site_cache_state:
        self.site.disable_cache()  # restore original state

final is set per title at
https://github.com/OpenSemanticLab/osw-python/blob/9aa6322/src/osw/core.py#L500-L508:

last = schema_title == fetchSchemaParam.schema_title[-1]
...
final=last

With two or more titles the sequence is:

  1. First title: snapshot False (cache disabled), enable the cache.
  2. Second title: snapshot True, because the first invocation already enabled
    it. Enable again.
  3. Last title: final is True, so the restore runs. But its own snapshot is
    True, so if not site_cache_state is false and disable_cache is never
    called.

The cache is left enabled. Only the single-title case restores correctly.

There is a second path with the same result: the early return for a missing
schema page at
https://github.com/OpenSemanticLab/osw-python/blob/9aa6322/src/osw/core.py#L621
returns before the restore, so if that title is the last one the restore is
skipped entirely.

Measured consequence

On osl.dev.afin-data.de at commit 9aa6322, a sequence of two update_task
calls against the same page reverted the status from "Done" back to "To do".
The second call read the page through the leaked cache, received the
pre-update jsondata, and wrote that stale content back.

Any code that reads an entity, modifies it and stores it is exposed to this,
because fetch_schema runs implicitly during ordinary read and write calls.

Suggested fix

Snapshot the cache state once for the whole fetch_schema operation rather than
once per title, and restore it in a finally block so the early returns cannot
skip it.

Related

#141 reports a different
side effect of the same implicit fetch_schema call: it rewrites
src/osw/model/entity.py. The two are separate defects in the same code path.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions