A revision identifier distinguishes one revision of an API resource from another. A revisable resource adds revisionId and revisionCreateTime fields while retaining its ordinary resource identifier; retrieving the resource by that identifier returns the latest revision. section 28.2
Choose an identifier strategy deliberately:
- Counting numbers provide chronological order but expose deleted revisions through gaps. section 28.3.1
- Timestamps tolerate gaps and convey ordering, but concurrent writes can produce collisions. section 28.3.1
- Random identifiers are opaque, uniquely identify one revision, and avoid exposing deletion history; use one consistent strategy across revisable resources. section 28.3.1 section 28.3.2
Populate revisionId when the resource is first created, regardless of the selected strategy. APIs commonly create revisions implicitly whenever stored data changes, though scheduled or explicitly requested creation is also possible. section 28.3.2
Addressing a specific revision
A Message can be requested with /chatRooms/1/messages/2@1234. The @ separator combines the resource ID and revision ID, allowing the standard get method to interpret the request without changing its interface. A response retains the resource ID and places the selected value in revisionId. section 28.3.3
Treat revision identifiers as inputs to revision-specific operations such as retrieval, restoration, and deletion. Restore an older revision by creating a new revision copied from it rather than moving or rewriting historical entries; expose deletion through a separate method to avoid confusing resource deletion with revision deletion. section 28.3.5 section 28.3.6
Listing 28.2 Example code to generate random resource revision identifiers
const crypto = require('crypto');
const base32Decode = require('base32-decode');
function generateRandomId(length: number): string {
const b32Chars = '012345689ABCDEFGHJKMNPQRSTVWXYTZ'; #1
let id = '';
for (let i = 0; i < length; i++) {
let rnd = crypto.randomInt(0, b32Chars.length);
id += b32Chars[rnd];
}
return id + getChecksumCharacter(id); #2
}
function getChecksumCharacter(value: string): string {
const bytes = Buffer.from(
base32Decode(value, 'Crockford')); #3
const intValue = BigInt(`0x${bytes.toString('hex')}`); #4
const checksumValue = Number(intValue % BigInt(37)); #5
const alphabet = '0123456789ABCDEFG' + #6
'HJKMNPQRSTVWXYZ*~$=U';
return alphabet[Math.abs(checksumValue)];
}
Inspect a random revision-identifier generator using Crockford Base32 characters and a checksum character. section 28.3.1
