Skip to content

Commit bd19c1b

Browse files
Merge remote-tracking branch 'origin/bugfix/ARSN-489' into w/8.2/bugfix/ARSN-489
2 parents d6b4219 + d58d22c commit bd19c1b

File tree

3 files changed

+48
-12
lines changed

3 files changed

+48
-12
lines changed

lib/storage/metadata/mongoclient/MongoClientInterface.ts

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import {
3737
} from 'mongodb';
3838
import { v4 as uuidv4 } from 'uuid';
3939

40-
import { generateVersionId as genVID } from '../../../versioning/VersionID';
40+
import { generateUniqueVersionId } from '../../../versioning/VersionID';
4141
import * as listAlgos from '../../../algos/list/exportAlgos';
4242
import LRUCache from '../../../algos/cache/LRUCache';
4343

@@ -75,8 +75,6 @@ const CONCURRENT_CURSORS = process.env.CONCURRENT_CURSORS ?
7575

7676
const initialInstanceID = process.env.INITIAL_INSTANCE_ID;
7777

78-
let uidCounter = 0;
79-
8078
const BUCKET_VERSIONS = require('../../../versioning/constants')
8179
.VersioningConstants.BucketVersioningKeyFormat;
8280
const DEFAULT_BUCKET_KEY_FORMAT =
@@ -87,12 +85,6 @@ const DEFAULT_BUCKET_KEY_FORMAT =
8785
const DB_PREFIXES = require('../../../versioning/constants')
8886
.VersioningConstants.DbPrefixes;
8987

90-
function generateVersionId(replicationGroupId) {
91-
// generate a unique number for each member of the nodejs cluster
92-
return genVID(`${process.pid}.${uidCounter++}`,
93-
replicationGroupId);
94-
}
95-
9688
function inc(str) {
9789
return str ? (str.slice(0, str.length - 1) +
9890
String.fromCharCode(str.charCodeAt(str.length - 1) + 1)) : str;
@@ -845,7 +837,7 @@ class MongoClientInterface {
845837
cb: ArsenalCallback<string>,
846838
isRetry?: boolean,
847839
) {
848-
const versionId = generateVersionId(this.replicationGroupId);
840+
const versionId = generateUniqueVersionId(this.replicationGroupId);
849841
objVal.versionId = versionId;
850842
const versionKey = formatVersionKey(objName, versionId, params.vFormat);
851843
const masterKey = formatMasterKey(objName, params.vFormat);
@@ -972,7 +964,7 @@ class MongoClientInterface {
972964
log: werelogs.Logger,
973965
cb: ArsenalCallback<string>,
974966
) {
975-
const versionId = generateVersionId(this.replicationGroupId);
967+
const versionId = generateUniqueVersionId(this.replicationGroupId);
976968
objVal.versionId = versionId;
977969
const masterKey = formatMasterKey(objName, params.vFormat);
978970
c.updateOne({ _id: masterKey },
@@ -1803,7 +1795,7 @@ class MongoClientInterface {
18031795
) {
18041796
const masterKey = formatMasterKey(objName, params.vFormat);
18051797
const versionKey = formatVersionKey(objName, params.versionId, params.vFormat);
1806-
const _vid = generateVersionId(this.replicationGroupId);
1798+
const _vid = generateUniqueVersionId(this.replicationGroupId);
18071799
async.series([
18081800
next => c.updateOne(
18091801
{

lib/versioning/VersionID.ts

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ const TEMPLATE_RG = new Array(LENGTH_RG + 1).join(' ');
2323

2424
export const S3_VERSION_ID_ENCODING_TYPE = process.env.S3_VERSION_ID_ENCODING_TYPE;
2525

26+
// Counter that is increased after each call to generateUniqueVersionId
27+
export let uidCounter = 0;
28+
export const versionIdSeed = getVersionIdSeed();
29+
2630
/**
2731
* Left-pad a string representation of a value with a given template.
2832
* For example: pad('foo', '00000') gives '00foo'.
@@ -87,6 +91,23 @@ function wait(span: number) {
8791
}
8892
}
8993

94+
export function getVersionIdSeed(): string {
95+
// The HOSTNAME environment variable is set by default by Kubernetes
96+
// and populated with the pod name, containing a suffix with a unique id
97+
// as a string.
98+
// By default, we rely on the pid, to account for multiple workers in
99+
// cluster mode. As a result, the unique id is either <pod-suffix>.<pid>
100+
// or <pid>.
101+
// If unique vID are needed in a multi cluster mode architecture (i.e.,
102+
// multiple server instances, each with multiple workers), the
103+
// HOSTNAME environment variable can be set.
104+
return `${process.env.HOSTNAME?.split('-').pop() || ''}${process.pid}`;
105+
}
106+
107+
export function generateUniqueVersionId(replicationGroupId: string): string {
108+
return generateVersionId(`${versionIdSeed}.${uidCounter++}`, replicationGroupId);
109+
}
110+
90111
/**
91112
* This function returns a "versionId" string indicating the current time as a
92113
* combination of the current time in millisecond, the position of the request

tests/unit/versioning/VersionID.spec.js

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,29 @@ function generateRandomVIDs(count) {
2222
const count = 1000000;
2323

2424
describe('test generating versionIds', () => {
25+
describe('getVersionIdSeed', () => {
26+
it('should return the correct versionIdSeed', () => {
27+
const versionIdSeed = VID.getVersionIdSeed();
28+
assert.strictEqual(versionIdSeed, process.pid.toString());
29+
});
30+
31+
it('should return the correct versionIdSeed when HOSTNAME is set', () => {
32+
process.env.HOSTNAME = 'test-pod-123';
33+
const versionIdSeed = VID.getVersionIdSeed();
34+
assert.strictEqual(versionIdSeed.startsWith('123'), true);
35+
});
36+
});
37+
38+
describe('generateUniqueVersionId', () => {
39+
it('should increase the uidCounter', () => {
40+
const versionId1 = VID.generateUniqueVersionId('somestring');
41+
const versionId2 = VID.generateUniqueVersionId('somestring');
42+
assert.notStrictEqual(versionId1, versionId2);
43+
assert(VID.uidCounter > 0);
44+
assert(VID.versionIdSeed);
45+
});
46+
});
47+
2548
describe('invalid IDs', () => {
2649
// A client can use the CLI to send requests with arbitrary version IDs.
2750
// These IDs may contain invalid characters and should be handled gracefully.

0 commit comments

Comments
 (0)