Skip to content

Commit df40cc3

Browse files
authored
Merge pull request #220 from weaviate/mt/allow-updating-config
Add missing functionality to update multi tenancy config
2 parents 0d444cd + 4f27ba1 commit df40cc3

File tree

6 files changed

+111
-16
lines changed

6 files changed

+111
-16
lines changed

src/collections/config/classes.ts

Lines changed: 20 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,15 @@ import { WeaviateInvalidInputError } from '../../errors.js';
33
import {
44
WeaviateClass,
55
WeaviateInvertedIndexConfig,
6+
WeaviateMultiTenancyConfig,
67
WeaviateReplicationConfig,
78
WeaviateVectorIndexConfig,
89
WeaviateVectorsConfig,
910
} from '../../openapi/types.js';
1011
import { QuantizerGuards } from '../configure/parsing.js';
1112
import {
1213
InvertedIndexConfigUpdate,
14+
MultiTenancyConfigUpdate,
1315
ReplicationConfigUpdate,
1416
VectorConfigUpdate,
1517
VectorIndexConfigFlatUpdate,
@@ -30,6 +32,11 @@ export class MergeWithExisting {
3032
current.invertedIndexConfig,
3133
update.invertedIndex
3234
);
35+
if (update.multiTenancy !== undefined)
36+
current.multiTenancyConfig = MergeWithExisting.multiTenancy(
37+
current.multiTenancyConfig,
38+
update.multiTenancy
39+
);
3340
if (update.replication !== undefined)
3441
current.replicationConfig = MergeWithExisting.replication(
3542
current.replicationConfig!,
@@ -56,7 +63,7 @@ export class MergeWithExisting {
5663

5764
static invertedIndex(
5865
current: WeaviateInvertedIndexConfig,
59-
update?: InvertedIndexConfigUpdate
66+
update: InvertedIndexConfigUpdate
6067
): WeaviateInvertedIndexConfig {
6168
if (current === undefined) throw Error('Inverted index config is missing from the class schema.');
6269
if (update === undefined) return current;
@@ -67,21 +74,27 @@ export class MergeWithExisting {
6774
return merged;
6875
}
6976

77+
static multiTenancy(
78+
current: WeaviateMultiTenancyConfig,
79+
update: MultiTenancyConfigUpdate
80+
): MultiTenancyConfigUpdate {
81+
if (current === undefined) throw Error('Multi-tenancy config is missing from the class schema.');
82+
return { ...current, ...update };
83+
}
84+
7085
static replication(
7186
current: WeaviateReplicationConfig,
72-
update?: ReplicationConfigUpdate
87+
update: ReplicationConfigUpdate
7388
): WeaviateReplicationConfig {
7489
if (current === undefined) throw Error('Replication config is missing from the class schema.');
75-
if (update === undefined) return current;
7690
return { ...current, ...update };
7791
}
7892

7993
static vectors(
8094
current: WeaviateVectorsConfig,
81-
update?: VectorConfigUpdate<string, VectorIndexType>[]
95+
update: VectorConfigUpdate<string, VectorIndexType>[]
8296
): WeaviateVectorsConfig {
8397
if (current === undefined) throw Error('Vector index config is missing from the class schema.');
84-
if (update === undefined) return current;
8598
update.forEach((v) => {
8699
const existing = current[v.name];
87100
if (existing !== undefined) {
@@ -96,9 +109,8 @@ export class MergeWithExisting {
96109

97110
static flat(
98111
current: WeaviateVectorIndexConfig,
99-
update?: VectorIndexConfigFlatUpdate
112+
update: VectorIndexConfigFlatUpdate
100113
): WeaviateVectorIndexConfig {
101-
if (update === undefined) return current;
102114
if (
103115
(QuantizerGuards.isPQUpdate(update.quantizer) && (current?.bq as any).enabled) ||
104116
(QuantizerGuards.isBQUpdate(update.quantizer) && (current?.pq as any).enabled)
@@ -115,9 +127,8 @@ export class MergeWithExisting {
115127

116128
static hnsw(
117129
current: WeaviateVectorIndexConfig,
118-
update?: VectorIndexConfigHNSWUpdate
130+
update: VectorIndexConfigHNSWUpdate
119131
): WeaviateVectorIndexConfig {
120-
if (update === undefined) return current;
121132
if (
122133
(QuantizerGuards.isBQUpdate(update.quantizer) &&
123134
(((current?.pq as any) || {}).enabled || ((current?.sq as any) || {}).enabled)) ||

src/collections/config/integration.test.ts

Lines changed: 38 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,12 @@
11
/* eslint-disable @typescript-eslint/no-non-null-assertion */
22
import { WeaviateUnsupportedFeatureError } from '../../errors.js';
33
import weaviate, { WeaviateClient, weaviateV2 } from '../../index.js';
4-
import { PropertyConfig, VectorIndexConfigDynamic, VectorIndexConfigHNSW } from './types/index.js';
4+
import {
5+
MultiTenancyConfig,
6+
PropertyConfig,
7+
VectorIndexConfigDynamic,
8+
VectorIndexConfigHNSW,
9+
} from './types/index.js';
510

611
const fail = (msg: string) => {
712
throw new Error(msg);
@@ -509,7 +514,7 @@ describe('Testing of the collection.config namespace', () => {
509514
});
510515

511516
it('should be able to create and get a collection with multi-tenancy enabled', async () => {
512-
const collectionName = 'TestCollectionConfigMultiTenancy';
517+
const collectionName = 'TestCollectionConfigCreateGetMultiTenancy';
513518
const collection = await client.collections.create({
514519
name: collectionName,
515520
multiTenancy: weaviate.configure.multiTenancy({
@@ -529,6 +534,37 @@ describe('Testing of the collection.config namespace', () => {
529534
expect(config.multiTenancy.enabled).toEqual(true);
530535
});
531536

537+
it('should be able to create and update a collection with multi-tenancy enabled', async () => {
538+
const collectionName = 'TestCollectionConfigCreateUpdateMultiTenancy';
539+
const collection = await client.collections.create({
540+
name: collectionName,
541+
multiTenancy: weaviate.configure.multiTenancy(),
542+
});
543+
let config = await collection.config.get();
544+
expect(config.multiTenancy).toEqual<MultiTenancyConfig>({
545+
enabled: true,
546+
autoTenantActivation: false,
547+
autoTenantCreation: false,
548+
});
549+
550+
await collection.config.update({
551+
multiTenancy: weaviate.reconfigure.multiTenancy({
552+
autoTenantActivation: true,
553+
autoTenantCreation: true,
554+
}),
555+
});
556+
config = await collection.config.get();
557+
558+
expect(config.name).toEqual(collectionName);
559+
expect(config.multiTenancy.autoTenantActivation).toEqual(
560+
await client.getWeaviateVersion().then((ver) => !ver.isLowerThan(1, 25, 2))
561+
);
562+
expect(config.multiTenancy.autoTenantCreation).toEqual(
563+
await client.getWeaviateVersion().then((ver) => !ver.isLowerThan(1, 25, 0))
564+
);
565+
expect(config.multiTenancy.enabled).toEqual(true);
566+
});
567+
532568
it('should be able update the config of a collection with legacy vectors', async () => {
533569
const clientV2 = weaviateV2.client({
534570
host: 'http://localhost:8080',

src/collections/config/types/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@ export * from './vectorizer.js';
55

66
import {
77
InvertedIndexConfigUpdate,
8+
MultiTenancyConfigUpdate,
89
ReplicationConfigUpdate,
910
VectorConfigUpdate,
1011
} from '../../configure/types/index.js';
@@ -103,6 +104,7 @@ export type CollectionConfig = {
103104
export type CollectionConfigUpdate = {
104105
description?: string;
105106
invertedIndex?: InvertedIndexConfigUpdate;
107+
multiTenancy?: MultiTenancyConfigUpdate;
106108
replication?: ReplicationConfigUpdate;
107109
vectorizers?:
108110
| VectorConfigUpdate<undefined, VectorIndexType>

src/collections/config/unit.test.ts

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
1-
import { WeaviateInvertedIndexConfig, WeaviateVectorsConfig } from '../../openapi/types';
1+
import {
2+
WeaviateInvertedIndexConfig,
3+
WeaviateMultiTenancyConfig,
4+
WeaviateVectorsConfig,
5+
} from '../../openapi/types';
26
import { MergeWithExisting } from './classes';
37

48
describe('Unit testing of the MergeWithExisting class', () => {
@@ -112,6 +116,12 @@ describe('Unit testing of the MergeWithExisting class', () => {
112116
},
113117
};
114118

119+
const multiTenancyConfig: WeaviateMultiTenancyConfig = {
120+
enabled: true,
121+
autoTenantActivation: false,
122+
autoTenantCreation: false,
123+
};
124+
115125
it('should merge a partial invertedIndexUpdate with existing schema', () => {
116126
const merged = MergeWithExisting.invertedIndex(JSON.parse(JSON.stringify(invertedIndex)), {
117127
bm25: {
@@ -341,4 +351,16 @@ describe('Unit testing of the MergeWithExisting class', () => {
341351
},
342352
});
343353
});
354+
355+
it('should merge full multi tenancy config with existing schema', () => {
356+
const merged = MergeWithExisting.multiTenancy(JSON.parse(JSON.stringify(multiTenancyConfig)), {
357+
autoTenantActivation: true,
358+
autoTenantCreation: true,
359+
});
360+
expect(merged).toEqual({
361+
enabled: true,
362+
autoTenantActivation: true,
363+
autoTenantCreation: true,
364+
});
365+
});
344366
});

src/collections/configure/index.ts

Lines changed: 23 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import {
22
InvertedIndexConfigCreate,
33
InvertedIndexConfigUpdate,
44
MultiTenancyConfigCreate,
5+
MultiTenancyConfigUpdate,
56
ReplicationConfigCreate,
67
ReplicationConfigUpdate,
78
ReplicationDeletionStrategy,
@@ -223,13 +224,13 @@ const reconfigure = {
223224
},
224225
},
225226
/**
226-
* Create a `ReplicationConfigUpdate` object to be used when defining the replication configuration of Weaviate.
227+
* Create a `ReplicationConfigUpdate` object to be used when updating the replication configuration of Weaviate.
227228
*
228229
* See [the docs](https://weaviate.io/developers/weaviate/concepts/replication-architecture#replication-vs-sharding) for more details.
229230
*
230-
* @param {boolean} [options.asyncEnabled] Whether asynchronous replication is enabled.
231-
* @param {ReplicationDeletionStrategy} [options.deletionStrategy] The deletion strategy when replication conflicts are detected between deletes and reads.
232-
* @param {number} [options.factor] The replication factor.
231+
* @param {boolean} [options.asyncEnabled] Whether to enable asynchronous replication.
232+
* @param {ReplicationDeletionStrategy} [options.deletionStrategy] The deletion strategy to update when replication conflicts are detected between deletes and reads.
233+
* @param {number} [options.factor] The replication factor to update.
233234
*/
234235
replication: (options: {
235236
asyncEnabled?: boolean;
@@ -242,6 +243,24 @@ const reconfigure = {
242243
factor: options.factor,
243244
};
244245
},
246+
/**
247+
* Create a `MultiTenancyConfigUpdate` object to be used when updating the multi-tenancy configuration of Weaviate.
248+
*
249+
* Note: You cannot update a single-tenant collection to become a multi-tenant collection. You must instead create a new multi-tenant collection and migrate the data over manually.
250+
*
251+
* @param {boolean} [options.autoTenantActivation] Whether to enable auto-tenant activation.
252+
* @param {boolean} [options.autoTenantCreation] Whether to enable auto-tenant creation.
253+
*
254+
*/
255+
multiTenancy: (options: {
256+
autoTenantActivation?: boolean;
257+
autoTenantCreation?: boolean;
258+
}): MultiTenancyConfigUpdate => {
259+
return {
260+
autoTenantActivation: options.autoTenantActivation,
261+
autoTenantCreation: options.autoTenantCreation,
262+
};
263+
},
245264
};
246265

247266
export {

src/collections/configure/types/base.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,11 @@ export type InvertedIndexConfigUpdate = {
3131

3232
export type MultiTenancyConfigCreate = RecursivePartial<MultiTenancyConfig>;
3333

34+
export type MultiTenancyConfigUpdate = {
35+
autoTenantActivation?: boolean;
36+
autoTenantCreation?: boolean;
37+
};
38+
3439
export type NestedPropertyCreate<T = undefined> = T extends undefined
3540
? {
3641
name: string;

0 commit comments

Comments
 (0)