couchbase-index-manager
Version:
Manage Couchbase indexes during the CI/CD process
1,195 lines • 41.1 kB
JavaScript
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
const configuration_1 = require("../configuration");
const index_manager_1 = require("../index-manager");
const create_index_mutation_1 = require("../plan/create-index-mutation");
const move_index_mutation_1 = require("../plan/move-index-mutation");
const resize_index_mutation_1 = require("../plan/resize-index-mutation");
const update_index_mutation_1 = require("../plan/update-index-mutation");
const index_definition_1 = require("./index-definition");
const defaultFakeIndex = {
id: 'fake',
name: 'fake',
scope: index_manager_1.DEFAULT_SCOPE,
collection: index_manager_1.DEFAULT_COLLECTION,
index_key: ['id'],
num_replica: 0,
num_partition: 0,
nodes: ['127.0.0.1:8091'],
retain_deleted_xattr: false,
state: 'online',
using: 'gsi',
};
function fakeIndex(index) {
return {
...defaultFakeIndex,
...index
};
}
describe('ctor', function () {
it('applies name', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(def.name).toBe('test');
});
it('applies index_key string', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(def.index_key)
.toStrictEqual(['key']);
});
it('applies index_key array', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: ['key1', 'key2'],
});
expect(def.index_key)
.toStrictEqual(['key1', 'key2']);
});
it('primary key with index_key throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
is_primary: true,
index_key: ['key'],
})).toThrowError();
});
it('primary key with condition throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
is_primary: true,
condition: '(`type` = "predicate")',
})).toThrowError();
});
it('secondary index without index_key throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
index_key: undefined,
})).toThrowError();
});
it('secondary index with empty index_key throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
index_key: [],
})).toThrowError();
});
it('manual replica with partition throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
partition: {
exprs: ['type'],
},
})).toThrowError();
});
it('node list sets num_replica', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
nodes: ['a', 'b'],
});
expect(def.num_replica).toBe(1);
});
it('no node list keeps num_replica', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
num_replica: 2,
});
expect(def.num_replica).toBe(2);
});
it('no num_replica is 0', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(def.num_replica).toBe(0);
});
it('no manual_replica is false', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(def.manual_replica).toBe(false);
});
it('manual_replica sets value', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
});
expect(def.manual_replica).toBe(true);
});
it('lifecycle copies values', function () {
const lifecycle = {
drop: true,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
lifecycle: lifecycle,
});
expect(def.lifecycle).not.toBe(lifecycle);
expect(def.lifecycle).toEqual(lifecycle);
});
it('partition copies values', function () {
const partition = {
exprs: ['test'],
strategy: configuration_1.PartitionStrategy.Hash,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: partition,
});
expect(def.partition).not.toBe(partition);
expect(def.partition).toEqual(partition);
});
it('partition null is undefined', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: null,
});
expect(def.partition).toBeUndefined();
});
it('no retain_deleted_xattr is false', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(def.retain_deleted_xattr).toBe(false);
});
it('retain_deleted_xattr sets value', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
retain_deleted_xattr: true,
});
expect(def.retain_deleted_xattr).toBe(true);
});
});
describe('applyOverride', function () {
it('applies index_key string', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
def.applyOverride({
index_key: 'key2',
});
expect(def.index_key)
.toStrictEqual(['key2']);
});
it('applies index_key array', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: ['key1', 'key2'],
});
def.applyOverride({
index_key: ['key3', 'key4'],
});
expect(def.index_key)
.toStrictEqual(['key3', 'key4']);
});
it('primary key with index_key throws error', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
is_primary: true,
});
expect(() => def.applyOverride({
name: 'test',
index_key: ['key'],
})).toThrowError();
});
it('primary key with condition throws error', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
is_primary: true,
});
expect(() => def.applyOverride({
name: 'test',
condition: '(`type` = "predicate")',
})).toThrowError();
});
it('secondary index without index_key throws error', function () {
expect(() => new index_definition_1.IndexDefinition({
name: 'test',
index_key: undefined,
})).toThrowError();
});
it('secondary index with empty index_key throws error', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(() => def.applyOverride({
name: 'test',
index_key: [],
})).toThrowError();
});
it('manual replica with partition throws error', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
});
expect(() => def.applyOverride({
partition: {
exprs: ['type'],
},
})).toThrowError();
});
it('node list sets num_replica', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
def.applyOverride({
nodes: ['a', 'b'],
});
expect(def.num_replica).toBe(1);
});
it('no node list keeps num_replica', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
def.applyOverride({
num_replica: 2,
});
expect(def.num_replica).toBe(2);
});
it('nodes and num_replica mismatch throws', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
expect(() => def.applyOverride({
nodes: ['a'],
num_replica: 2,
})).toThrowError();
});
it('partitioned nodes and num_replica mismatch succeeds', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: {
exprs: ['type'],
},
});
def.applyOverride({
nodes: ['a', 'b', 'c'],
num_replica: 2,
});
expect(def.nodes).toHaveLength(3);
expect(def.num_replica).toBe(2);
});
it('nodes and num_replica match succeeds', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
def.applyOverride({
nodes: ['a', 'b', 'c'],
num_replica: 2,
});
expect(def.nodes).toHaveLength(3);
expect(def.num_replica).toBe(2);
});
it('no manual_replica is unchanged', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
});
def.applyOverride({});
expect(def.manual_replica).toBe(true);
});
it('manual_replica sets value', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
});
def.applyOverride({
manual_replica: true,
});
expect(def.manual_replica).toBe(true);
});
it('lifecycle copies values', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
lifecycle: {
initial: 1,
},
});
const lifecycle = {
drop: true,
};
def.applyOverride({
lifecycle: lifecycle,
});
expect(def.lifecycle).not.toBe(lifecycle);
expect(def.lifecycle).toHaveProperty('initial', 1);
expect(def.lifecycle).toHaveProperty('drop', true);
});
it('partition undefined leaves unmodified', function () {
const partition = {
exprs: ['test'],
strategy: configuration_1.PartitionStrategy.Hash,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: partition,
});
def.applyOverride({});
expect(def.partition).toEqual(partition);
});
it('partition null clears', function () {
const partition = {
exprs: ['test'],
strategy: configuration_1.PartitionStrategy.Hash,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: partition,
});
def.applyOverride({
partition: null,
});
expect(def.partition).toBeUndefined();
});
it('partition updates strategy', function () {
var _a;
const partition = {
exprs: ['test'],
strategy: configuration_1.PartitionStrategy.Hash,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: partition,
});
def.applyOverride({
partition: {
strategy: 'other',
},
});
expect(def.partition).toHaveProperty('strategy', 'other');
expect((_a = def.partition) === null || _a === void 0 ? void 0 : _a.exprs)
.toStrictEqual(partition.exprs);
});
it('partition replaces exprs', function () {
var _a;
const partition = {
exprs: ['test', 'test2'],
strategy: configuration_1.PartitionStrategy.Hash,
};
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: partition,
});
def.applyOverride({
partition: {
exprs: ['test3'],
},
});
expect(def.partition).toHaveProperty('strategy', configuration_1.PartitionStrategy.Hash);
expect((_a = def.partition) === null || _a === void 0 ? void 0 : _a.exprs)
.toStrictEqual(['test3']);
});
});
describe('getMutation partition change', function () {
it('ignores matching partition', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
},
});
const mutations = [...def.getMutations({
currentIndexes: [
fakeIndex({
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test`)',
nodes: ['a:8091'],
}),
],
})];
expect(mutations).toHaveLength(0);
});
it('ignores matching num_partition', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
num_partition: 3,
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test`)',
num_partition: 3,
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(0);
});
it('ignores missing num_partition', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test`)',
num_partition: 8,
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(0);
});
it('updates if partition does not match', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test2`)',
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
});
it('updates if num_partition does not match', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
num_partition: 3,
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test2`)',
num_partition: 8,
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
});
it('updates if partition removed', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
partition: 'HASH(`test2`)',
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
});
it('updates if partition added', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
partition: {
exprs: ['`test`'],
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
});
});
describe('getMutation manual replica node changes', function () {
it('performs node move as an update', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
manual_replica: true,
nodes: ['a', 'b'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091'],
},
{
name: 'test_replica1',
index_key: ['`key`'],
nodes: ['c:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
expect(mutations[0].isSafe()).toBe(true);
expect(mutations[0]).toMatchObject({
name: 'test_replica1',
phase: 1,
});
});
it('ignores node swap', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
manual_replica: true,
nodes: ['a', 'b'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['b:8091'],
},
{
name: 'test_replica1',
index_key: ['`key`'],
nodes: ['a:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(0);
});
it('creates new replicas first', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
manual_replica: true,
nodes: ['a', 'b', 'c'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['d:8091'],
},
].map(fakeIndex),
})];
expect(mutations).toHaveLength(3);
const updates = mutations.filter((m) => m instanceof update_index_mutation_1.UpdateIndexMutation);
expect(updates).toHaveLength(1);
expect(mutations[0].isSafe()).toBe(true);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 2,
});
const creates = mutations.filter((m) => m instanceof create_index_mutation_1.CreateIndexMutation);
expect(creates).toHaveLength(2);
for (const create of creates) {
expect(create).toMatchObject({
phase: 1,
});
}
});
});
describe('getMutation automatic replica node changes', function () {
it('performs single move mutation', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a', 'b'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'c:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(move_index_mutation_1.MoveIndexMutation);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1
});
});
it('ignores node swap', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a', 'b'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['b:8091', 'a:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(0);
});
it('num_replica change gives unsafe update', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
num_replica: 2,
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
expect(mutations[0].isSafe()).toBe(false);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('num_replica addition from zero gives unsafe update', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
num_replica: 1,
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 0,
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
expect(mutations[0].isSafe()).toBe(false);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('num_replica change gives resize on 6.5', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
num_replica: 2,
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 6,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(resize_index_mutation_1.ResizeIndexMutation);
expect(mutations[0].isSafe()).toBe(true);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('num_replica addition from zero gives resize on 6.5', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
num_replica: 1,
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091'],
num_replica: 0,
},
].map(fakeIndex),
clusterVersion: {
major: 6,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(resize_index_mutation_1.ResizeIndexMutation);
expect(mutations[0].isSafe()).toBe(true);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('partitioned num_replica change gives unsafe update', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
num_replica: 2,
partition: {
exprs: ['`type`'],
},
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 1,
partition: 'HASH(`type`)',
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
expect(mutations[0].isSafe()).toBe(false);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('node length change gives unsafe update', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 5,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(update_index_mutation_1.UpdateIndexMutation);
expect(mutations[0].isSafe()).toBe(false);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
it('node length change gives resize on 6.5', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091', 'b:8091'],
num_replica: 1,
},
].map(fakeIndex),
clusterVersion: {
major: 6,
minor: 5,
},
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(resize_index_mutation_1.ResizeIndexMutation);
expect(mutations[0].isSafe()).toBe(true);
expect(mutations[0]).toMatchObject({
name: 'test',
phase: 1,
});
});
});
describe('getMutation scope/collection', function () {
it('matches default scope/collection', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a:8091'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
index_key: ['`key`'],
nodes: ['a:8091']
},
].map(fakeIndex)
})];
expect(mutations).toHaveLength(0);
});
it('does not match specific scope/collection with the same name', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: '`key`',
nodes: ['a:8091'],
});
const mutations = [...def.getMutations({
currentIndexes: [
{
name: 'test',
scope: 'inventory',
collection: 'hotel',
index_key: ['`key`'],
nodes: ['a:8091']
},
].map(fakeIndex)
})];
expect(mutations).toHaveLength(1);
expect(mutations[0]).toBeInstanceOf(create_index_mutation_1.CreateIndexMutation);
});
});
describe('normalizeNodeList', function () {
describe('auto replica', function () {
it('sorts node lists', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
nodes: ['b', 'c', 'a'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:8091', 'b:8091', 'c:8091']);
});
it('adds port numbers', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
nodes: ['a', 'b', 'c'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:8091', 'b:8091', 'c:8091']);
});
it('ignores defined port numbers', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
nodes: ['a:18091', 'b', 'c'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:18091', 'b:8091', 'c:8091']);
});
});
describe('manual replica', function () {
it('sorts node lists', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['b', 'c', 'a'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:8091', 'b:8091', 'c:8091']);
});
it('adds port numbers', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['a', 'b', 'c'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:8091', 'b:8091', 'c:8091']);
});
it('ignores defined port numbers', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['a:18091', 'b', 'c'],
});
def.normalizeNodeList([]);
expect(def.nodes)
.toStrictEqual(['a:18091', 'b:8091', 'c:8091']);
});
it('sorts to match replicas', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['a', 'b', 'c'],
});
def.normalizeNodeList([
{
name: 'test',
nodes: ['b:8091'],
},
{
name: 'test_replica1',
nodes: ['c:8091'],
},
{
name: 'test_replica2',
nodes: ['a:8091'],
},
].map(fakeIndex));
expect(def.nodes)
.toStrictEqual(['b:8091', 'c:8091', 'a:8091']);
});
it('missing replicas get remaining nodes', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['a', 'b', 'c'],
});
def.normalizeNodeList([
{
name: 'test',
nodes: ['b:8091'],
},
].map(fakeIndex));
expect(def.nodes)
.toStrictEqual(['b:8091', 'a:8091', 'c:8091']);
});
it('missing replica in middle gets remaining node', function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
manual_replica: true,
nodes: ['a', 'b', 'c'],
});
def.normalizeNodeList([
{
name: 'test',
nodes: ['b:8091'],
},
{
name: 'test_replica2',
nodes: ['a:8091'],
},
].map(fakeIndex));
expect(def.nodes)
.toStrictEqual(['b:8091', 'c:8091', 'a:8091']);
});
});
});
describe('normalize', function () {
it('does nothing for primary index', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
is_primary: true,
});
const getQueryPlan = jest.fn().mockResolvedValue({});
const manager = {
bucketName: 'test',
getQueryPlan: getQueryPlan,
};
await def.normalize(manager);
expect(getQueryPlan).not.toBeCalled();
});
it('replaces keys', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
condition: 'type = \'beer\'',
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`' },
],
where: '`type` = "beer"',
})
}));
await def.normalize(indexManager());
expect(def.index_key)
.toStrictEqual(['`key`']);
});
it('handles descending keys', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
condition: 'type = \'beer\'',
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`', desc: true },
],
where: '`type` = "beer"',
})
}));
await def.normalize(indexManager());
expect(def.index_key)
.toStrictEqual(['`key` DESC']);
});
it('replaces condition', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
condition: 'type = \'beer\'',
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`' },
],
where: '`type` = "beer"'
})
}));
await def.normalize(indexManager());
expect(def.condition).toBe('`type` = "beer"');
});
it('plan without condition leaves condition as empty string', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
condition: '',
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`' },
],
})
}));
await def.normalize(indexManager());
expect(def.condition).toBe('');
});
it('replaces partition', async function () {
var _a;
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: {
exprs: ['test'],
},
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`' },
],
partition: {
exprs: ['test2'],
strategy: 'HASH',
},
})
}));
await def.normalize(indexManager());
expect(def.partition).toHaveProperty('strategy', 'HASH');
expect((_a = def.partition) === null || _a === void 0 ? void 0 : _a.exprs)
.toStrictEqual(['test2']);
});
it('plan without partition leaves partition undefined', async function () {
const def = new index_definition_1.IndexDefinition({
name: 'test',
index_key: 'key',
partition: {
exprs: ['test'],
},
});
const indexManager = jest.fn(() => ({
bucketName: 'test',
getQueryPlan: jest.fn().mockResolvedValue({
keys: [
{ expr: '`key`' },
],
})
}));
await def.normalize(indexManager());
expect(def.partition).toBeUndefined();
});
});
//# sourceMappingURL=index-definition.spec.js.map