@salto-io/da-playa
Version:
Deploy locks management (CLI and Slackbot)
127 lines • 4.4 kB
JavaScript
;
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.Locker = exports.LockModelDetails = exports.ModelName = void 0;
const dynamodb_1 = __importDefault(require("dynamodb"));
const joi_1 = __importDefault(require("joi"));
const data_1 = require("../data");
const TTL = 20 * 60 * 1000;
exports.ModelName = 'lock';
const locksDynamoDbModel = {
hashKey: 'id',
rangeKey: 'env',
timestamps: false,
schema: {
user: joi_1.default.string().required(),
id: dynamodb_1.default.types.uuid(),
env: joi_1.default.string().required(),
active: joi_1.default.boolean(),
started: joi_1.default.number().required(),
ended: joi_1.default.number(),
uberlock: joi_1.default.boolean(),
meta: joi_1.default.string(),
},
tableName: 'DaPlayaLocks',
};
exports.LockModelDetails = {
Model: locksDynamoDbModel,
ModelName: exports.ModelName,
};
const Locker = async ({ dynamoDBRegion, dynamoDbUri, }) => {
const LocksDB = (0, data_1.Data)({
model: locksDynamoDbModel,
modelName: exports.ModelName,
dynamoDBRegion,
dynamoDbUri,
});
const getActiveLocks = (env, user) => {
const ttl = new Date().getTime() - TTL;
const userFilterString = user ? ' AND #user = :user' : '';
const filterEnvExpression = '#env = :env';
const filterActiveOrUber = '(#started > :ttl OR #uberlock = :true) AND #active = :true';
const filterExpression = `${filterEnvExpression} AND (${filterActiveOrUber})${userFilterString}`;
const filterAttributeValues = {
':true': true,
':env': env,
':ttl': ttl,
...(user
? {
':user': user,
}
: {}),
};
const filterAttributeNames = {
'#env': 'env',
'#active': 'active',
'#started': 'started',
'#uberlock': 'uberlock',
...(user
? {
'#user': 'user',
}
: {}),
};
return LocksDB.get({
filterExpression,
filterAttributeValues,
filterAttributeNames,
});
};
const updatePromiseByUser = async (env, user, uberlock = false) => {
const currentLock = await getActiveLocks(env, user);
if (!currentLock.length) {
return {
notLockedBy: user.toLowerCase(),
};
}
if (currentLock[0].uberlock && !uberlock) {
return {
currentLock: currentLock[0],
};
}
return LocksDB.set({
...currentLock[0],
active: false,
ended: new Date().getTime(),
});
};
const createLock = async ({ user, env, meta, uberlock, }) => LocksDB.create({
user: user.toLowerCase(),
env: env.toLowerCase(),
active: true,
started: new Date().getTime(),
meta,
uberlock,
});
return {
lock: async ({ user, env, meta, uberlock = false }) => {
const activeLocks = await getActiveLocks(env);
const existingUberLock = activeLocks.find(x => x.uberlock);
if (existingUberLock) {
return existingUberLock.user !== user ? {
// LockRejected due to other user uberlocking
currentLock: existingUberLock,
} : existingUberLock;
}
if (uberlock) {
return createLock({ user, env, meta, uberlock });
}
const currentUserLock = activeLocks.find(x => x.user === user);
if (currentUserLock) {
return currentUserLock;
}
if (!activeLocks.length) {
return createLock({ user, env, meta, uberlock });
}
return {
currentLock: activeLocks[0],
};
},
release: async ({ env, user, uberlock }) => updatePromiseByUser(env, user, uberlock),
locks: async (env, user) => getActiveLocks(env, user),
};
};
exports.Locker = Locker;
//# sourceMappingURL=index.js.map