CodamAIDocs
Topicdone

Rollback for files

How the file content is copied back during a rollback, and why the current state is saved first.

Variants
content comes back with the recordcurrent content is saved as a version firstrollback of a rollbackrevision without fileVersion → content stayssame content as nowname, size and type

What this is about

A file model has two parts: the record in the database and the content in the file storage. If the model is audited, every old content stays as a version, and every revision of the record remembers in fileVersion which content belongs to it. See File versions.

A rollback sets both parts back together: the record to the state of the revision, and the content to the version named in that revision.

Before and after in the storage

A contract was uploaded three times. Now it is rolled back to the revision of the first edition:

Before – the record carries fileVersion 1790000300000:

File in storageContent
<fileId>“edition three” (current)
<fileId>.1790000200000“edition two”
<fileId>.1790000100000“edition one”

After – POST /fileasset/f1…/rollback/17, the record carries fileVersion 1790000100000:

File in storageContent
<fileId>“edition one” (current, a copy)
<fileId>.1790000300000“edition three” (newly kept as a version)
<fileId>.1790000200000“edition two”
<fileId>.1790000100000“edition one” (stays as a version)

The current content gets the identifier of the version it is a copy of. So record and content match again: fileVersion 1790000100000 means “edition one”.

The flow

Rolling back a file model to revision 17
  1. 1
    Client→CDMS
    POST /fileasset/f1…/rollback/17 with response
  2. 2
    CDMS
    checks visibility and rollback role like for every rollback
  3. 3
    CDMS
    remembers the fileVersion the record carries now: 1790000300000
    That is the identifier of the content currently in the storage.
  4. 4
    CDMS→Database
    sets the record back to revision 17. It now carries fileVersion 1790000100000.
  5. 5
    CDMS→File storage
    Does version 1790000100000 exist?
    No → 500 file-version-not-found, the change in the database is discarded.
  6. 6
    CDMS→File storage
    copies <fileId>.1790000100000 to an intermediate file next to <fileId>
    Copy, not move: the version stays and can be restored again later. "Edition three" is still current.
  7. 7
    CDMS
    sets fileSize and mimeType from the restored content
  8. 8
    CDMS→Database
    after hooks, flush, read back, commit
    If something fails here, the intermediate file is discarded. Record and content stay on "edition three".
  9. 9
    CDMS→File storage
    renames the current content to <fileId>.1790000300000 and the intermediate file to <fileId>
    That way "edition three" is kept, and "edition one" becomes current in one step.
    Result: GET /fileasset/f1…/file returns "edition one". The history has a new MOD revision.

Why the current content is saved first

Without this step the rollback would overwrite the current content. “Edition three” would then be gone, although the history still contains a revision with fileVersion 1790000300000. A rollback to that revision would find no content any more.

This way the same rule applies as for the record: history is not rewritten. Every revision finds its content, including the revision right before the rollback.

The variants

Rollback and file content

When: The target revision names a different version than the current state.

The current content becomes a version, the target version is copied to the current place.

Result: Download returns the old content.

When: After the rollback to 17, the object is rolled back to the revision before it.

The current content is a copy of version 1790000100000, which already exists. So CDMS does not store it twice, but only removes the copy. Then it copies version 1790000300000 back.

Result: "Edition three" is current again, no file is stored twice.

When: New content is uploaded after the rollback.

Here too the current content is only a copy of an existing version. It is removed instead of being kept a second time, and the new content takes its place.

When: The target revision dates from the time before the record had a fileVersion.

The record is rolled back, the content stays as it is. CDMS cannot tell for sure which content belongs to this revision, and it does not guess.

When: Since the target revision only the record was changed, for example renamed, but no new content was uploaded.

The target revision names the same fileVersion as the current state. So the content is already the right one. CDMS only rolls back the record and leaves the content as it is.

Result: The old name and the other fields are back, the download returns the same content as before.

Name, size and type

FieldAfter the rollback
namethe name from the target revision, like every simple field
fileVersionthe identifier of the restored version
fileSizemeasured again on the restored content
mimeTypedetermined again from the extension of the name, as on upload
fileIdstays, it determines the place in the storage

Pitfalls

What comes next

Sources in the code and the knowledge base
  • CDMS/cdms-system-layer – AbstractSystemLayer.historyRollback (currentFileVersion before the rollback), AbstractLayer.rollbackFileContent (targetVersion null → nothing), currentFileVersion
  • CDMS/cdms-localfs-storage – LocalFSFileController.stageRollback (same identifier → nothing to do, file-version-not-found, copy to an intermediate file, applyStoredMetadata), Staged.publish (retainCurrentContent, rename), retainCurrentContent (existing version → current copy is deleted); FileUtils.versionPath; ADR-021
  • CDMS/cdms-integrationtest – AbstractFileRollbackTest (rollbackRestoresTheContentOfThatRevision, rollbackAddsARevisionInsteadOfRewritingOne, rollbackWithoutTheRoleIsRefused, aRefusedRollbackKeepsTheCurrentContent, rollingBackARenameKeepsTheContent)
  • documentation/50-auditierung/01-auditing-und-historie.md (files during rollback)
Search