Skip to content

Commit d47bc69

Browse files
Merge pull request #910 from appwrite/feat-match-indexes
feat(cli): Pushing logic for indexes
2 parents 10aa1db + f19afc1 commit d47bc69

File tree

2 files changed

+75
-16
lines changed

2 files changed

+75
-16
lines changed

templates/cli/lib/commands/push.js.twig

Lines changed: 69 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ const chalk = require('chalk');
22
const inquirer = require("inquirer");
33
const JSONbig = require("json-bigint")({ storeAsString: false });
44
const { Command } = require("commander");
5-
const { localConfig, globalConfig } = require("../config");
5+
const { localConfig, globalConfig, KeyAttributes } = require("../config");
66
const { Spinner, SPINNER_ARC, SPINNER_DOTS } = require('../spinner');
77
const { paginate } = require('../paginate');
88
const { questionsPushBuckets, questionsPushTeams, questionsPushFunctions, questionsGetEntrypoint, questionsPushCollections, questionsConfirmPushCollections, questionsPushMessagingTopics, questionsPushResources } = require("../questions");
@@ -37,6 +37,7 @@ const {
3737
databasesUpdateRelationshipAttribute,
3838
databasesCreateRelationshipAttribute,
3939
databasesDeleteAttribute,
40+
databasesDeleteIndex,
4041
databasesListAttributes,
4142
databasesListIndexes,
4243
databasesUpdateCollection
@@ -254,6 +255,41 @@ const awaitPools = {
254255
iteration + 1
255256
);
256257
},
258+
deleteIndexes: async (databaseId, collectionId, indexesKeys, iteration = 1) => {
259+
if (iteration > pollMaxDebounces) {
260+
return false;
261+
}
262+
263+
if (pollMaxDebounces === POLL_DEFAULT_VALUE) {
264+
let steps = Math.max(1, Math.ceil(attributeKeys.length / STEP_SIZE));
265+
if (steps > 1 && iteration === 1) {
266+
pollMaxDebounces *= steps;
267+
268+
log('Found a large number of indexes to be deleted. Increasing timeout to ' + (pollMaxDebounces * POLL_DEBOUNCE / 1000 / 60) + ' minutes')
269+
}
270+
}
271+
272+
const { indexes } = await paginate(databasesListIndexes, {
273+
databaseId,
274+
collectionId,
275+
parseOutput: false
276+
}, 100, 'indexes');
277+
278+
const ready = indexesKeys.filter(index => indexes.includes(index.key));
279+
280+
if (ready.length === 0) {
281+
return true;
282+
}
283+
284+
await new Promise(resolve => setTimeout(resolve, POLL_DEBOUNCE));
285+
286+
return await awaitPools.expectIndexes(
287+
databaseId,
288+
collectionId,
289+
indexesKeys,
290+
iteration + 1
291+
);
292+
},
257293
expectIndexes: async (databaseId, collectionId, indexKeys, iteration = 1) => {
258294
if (iteration > pollMaxDebounces) {
259295
return false;
@@ -536,8 +572,18 @@ const updateAttribute = async (databaseId, collectionId, attribute) => {
536572
})
537573
}
538574
}
539-
const deleteAttribute = async (collection, attribute) => {
540-
log(`Deleting attribute ${attribute.key} of ${collection.name} ( ${collection['$id']} )`);
575+
const deleteAttribute = async (collection, attribute, isIndex = false) => {
576+
log(`Deleting ${isIndex ? 'index' : 'attribute'} ${attribute.key} of ${collection.name} ( ${collection['$id']} )`);
577+
578+
if (isIndex) {
579+
await databasesDeleteIndex({
580+
databaseId: collection['databaseId'],
581+
collectionId: collection['$id'],
582+
key: attribute.key,
583+
parseOutput: false
584+
});
585+
return;
586+
}
541587

542588
await databasesDeleteAttribute({
543589
databaseId: collection['databaseId'],
@@ -568,6 +614,10 @@ const checkAttributeChanges = (remote, local, collection, recraeting = true) =>
568614
let attribute = remote;
569615

570616
for (let key of Object.keys(remote)) {
617+
if (!KeyAttributes.has(key)) {
618+
continue;
619+
}
620+
571621
if (changeableKeys.includes(key)) {
572622
if (!recraeting) {
573623
if (remote[key] !== local[key]) {
@@ -583,7 +633,12 @@ const checkAttributeChanges = (remote, local, collection, recraeting = true) =>
583633
continue;
584634
}
585635

586-
if (remote[key] !== local[key]) {
636+
if (Array.isArray(remote[key]) && Array.isArray(local[key])) {
637+
if (JSON.stringify(remote[key]) !== JSON.stringify(local[key])) {
638+
const bol = reason === '' ? '' : '\n';
639+
reason += `${bol}${key} changed from ${chalk.red(remote[key])} to ${chalk.green(local[key])}`;
640+
}
641+
} else if (remote[key] !== local[key]) {
587642
const bol = reason === '' ? '' : '\n';
588643
reason += `${bol}${key} changed from ${chalk.red(remote[key])} to ${chalk.green(local[key])}`;
589644
}
@@ -612,12 +667,9 @@ const generateChangesObject = (attribute, collection, isAdding) => {
612667
/**
613668
* Filter deleted and recreated attributes,
614669
* return list of attributes to create
615-
* @param remoteAttributes
616-
* @param localAttributes
617-
* @param collection
618670
* @returns {Promise<*|*[]>}
619671
*/
620-
const attributesToCreate = async (remoteAttributes, localAttributes, collection) => {
672+
const attributesToCreate = async (remoteAttributes, localAttributes, collection, isIndex = false) => {
621673

622674
const deleting = remoteAttributes.filter((attribute) => !attributesContains(attribute, localAttributes)).map((attr) => generateChangesObject(attr, collection, false));
623675
const adding = localAttributes.filter((attribute) => !attributesContains(attribute, remoteAttributes)).map((attr) => generateChangesObject(attr, collection, true));
@@ -639,10 +691,10 @@ const attributesToCreate = async (remoteAttributes, localAttributes, collection)
639691
}));
640692

641693
if (!cliConfig.force) {
642-
if (deleting.length > 0) {
694+
if (deleting.length > 0 && !isIndex) {
643695
log(`Attribute deletion will cause ${chalk.red('loss of data')}`);
644696
}
645-
if (conflicts.length > 0) {
697+
if (conflicts.length > 0 && !isIndex) {
646698
log(`Attribute recreation will cause ${chalk.red('loss of data')}`);
647699
}
648700

@@ -655,7 +707,7 @@ const attributesToCreate = async (remoteAttributes, localAttributes, collection)
655707

656708
if (conflicts.length > 0) {
657709
changedAttributes = conflicts.map((change) => change.attribute);
658-
await Promise.all(changedAttributes.map((changed) => deleteAttribute(collection, changed)));
710+
await Promise.all(changedAttributes.map((changed) => deleteAttribute(collection, changed, isIndex)));
659711
remoteAttributes = remoteAttributes.filter((attribute) => !attributesContains(attribute, changedAttributes))
660712
}
661713

@@ -665,7 +717,7 @@ const attributesToCreate = async (remoteAttributes, localAttributes, collection)
665717
}
666718

667719
const deletingAttributes = deleting.map((change) => change.attribute);
668-
await Promise.all(deletingAttributes.map((attribute) => deleteAttribute(collection, attribute)));
720+
await Promise.all(deletingAttributes.map((attribute) => deleteAttribute(collection, attribute, isIndex)));
669721
const attributeKeys = [...remoteAttributes.map(attribute => attribute.key), ...deletingAttributes.map(attribute => attribute.key)]
670722

671723
if (attributeKeys.length) {
@@ -1149,13 +1201,16 @@ const pushCollection = async ({ returnOnZero, attempts } = { returnOnZero: false
11491201
// Serialize attribute actions
11501202
for (let collection of collections) {
11511203
let attributes = collection.attributes;
1204+
let indexes = collection.indexes;
11521205

11531206
if (collection.isExisted) {
11541207
attributes = await attributesToCreate(collection.remoteVersion.attributes, collection.attributes, collection);
1208+
indexes = await attributesToCreate(collection.remoteVersion.indexes, collection.indexes, collection, true);
11551209

1156-
if (Array.isArray(attributes) && attributes.length <= 0) {
1210+
if ((Array.isArray(attributes) && attributes.length <= 0) && (Array.isArray(indexes) && indexes.length <= 0)) {
11571211
continue;
11581212
}
1213+
11591214
}
11601215

11611216
log(`Pushing collection ${collection.name} ( ${collection['databaseId']} - ${collection['$id']} ) attributes`)
@@ -1167,7 +1222,7 @@ const pushCollection = async ({ returnOnZero, attempts } = { returnOnZero: false
11671222
}
11681223

11691224
try {
1170-
await createIndexes(collection.indexes, collection);
1225+
await createIndexes(indexes, collection);
11711226
} catch (e) {
11721227
throw e;
11731228
}

templates/cli/lib/config.js.twig

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ const KeyAttributes = new Set([
1717
"size",
1818
"default",
1919
// integer and float
20-
"min",
20+
"min",
2121
"max",
2222
// email, enum, URL, IP, and datetime
2323
"format",
@@ -29,7 +29,10 @@ const KeyAttributes = new Set([
2929
"twoWay",
3030
"twoWayKey",
3131
"onDelete",
32-
"side"
32+
"side",
33+
// Indexes
34+
"attributes",
35+
"orders"
3336
]);
3437
const KeyIndexes = new Set(["key", "type", "status", "attributes", "orders"]);
3538

@@ -604,4 +607,5 @@ class Global extends Config {
604607
module.exports = {
605608
localConfig: new Local(),
606609
globalConfig: new Global(),
610+
KeyAttributes,
607611
};

0 commit comments

Comments
 (0)