Skip to content

Commit

Permalink
refactor(search): extract generic ModelSearchIndexer
Browse files Browse the repository at this point in the history
  • Loading branch information
emorikawa committed Nov 14, 2016
1 parent f9756c2 commit e942b91
Show file tree
Hide file tree
Showing 3 changed files with 90 additions and 67 deletions.
73 changes: 6 additions & 67 deletions internal_packages/search-index/lib/contact-search-index-store.es6
Original file line number Diff line number Diff line change
@@ -1,77 +1,17 @@
import {
Contact,
DatabaseStore,
ModelSearchIndexer,
} from 'nylas-exports';

const INDEX_VERSION = 1;
class ContactSearchIndexStore extends ModelSearchIndexer {

class ContactSearchIndexStore {
constructor() {
this.unsubscribers = []
}

activate() {
this.initializeIndex();
this.unsubscribers = [
DatabaseStore.listen(this.onDataChanged),
];
}

deactivate() {
this.unsubscribers.forEach(unsub => unsub())
}

initializeIndex() {
if (NylasEnv.config.get('contactSearchIndexVersion') !== INDEX_VERSION) {
DatabaseStore.dropSearchIndex(Contact)
.then(() => DatabaseStore.createSearchIndex(Contact))
.then(() => this.buildIndex())
}
}

buildIndex(offset = 0) {
const indexingPageSize = 1000;
const indexingPageDelay = 1000;

DatabaseStore.findAll(Contact).limit(indexingPageSize).offset(offset).then((contacts) => {
if (contacts.length === 0) {
NylasEnv.config.set('contactSearchIndexVersion', INDEX_VERSION)
return;
}
Promise.each(contacts, (contact) => {
return DatabaseStore.indexModel(contact, this.getIndexDataForContact(contact))
}).then(() => {
setTimeout(() => {
this.buildIndex(offset + contacts.length);
}, indexingPageDelay);
});
});
}
modelClass() { return Contact }

/**
* When a contact gets updated we will update the search index with the data
* from that contact if the account it belongs to is not being currently
* synced.
*
* When the account is successfully synced, its contacts will be added to the
* index either via `onAccountsChanged` or via `initializeIndex` when the app
* starts
*/
onDataChanged = (change) => {
if (change.objectClass !== Contact.name) {
return;
}
configKey() { return "contactSearchIndexVersion" }

change.objects.forEach((contact) => {
if (change.type === 'persist') {
DatabaseStore.indexModel(contact, this.getIndexDataForContact(contact))
} else {
DatabaseStore.unindexModel(contact)
}
});
}
INDEX_VERSION() { return 1 }

getIndexDataForContact(contact) {
getIndexDataForModel(contact) {
return {
content: [
contact.name ? contact.name : '',
Expand All @@ -80,7 +20,6 @@ class ContactSearchIndexStore {
].join(' '),
};
}

}

export default new ContactSearchIndexStore()
1 change: 1 addition & 0 deletions src/global/nylas-exports.es6
Original file line number Diff line number Diff line change
Expand Up @@ -205,6 +205,7 @@ lazyLoad(`MailRulesTemplates`, 'mail-rules-templates');
lazyLoad(`MailRulesProcessor`, 'mail-rules-processor');
lazyLoad(`MailboxPerspective`, 'mailbox-perspective');
lazyLoad(`NativeNotifications`, 'native-notifications');
lazyLoad(`ModelSearchIndexer`, 'services/model-search-indexer');
lazyLoad(`SanitizeTransformer`, 'services/sanitize-transformer');
lazyLoad(`QuotedHTMLTransformer`, 'services/quoted-html-transformer');
lazyLoad(`InlineStyleTransformer`, 'services/inline-style-transformer');
Expand Down
83 changes: 83 additions & 0 deletions src/services/model-search-indexer.es6
Original file line number Diff line number Diff line change
@@ -0,0 +1,83 @@
import { DatabaseStore } from 'nylas-exports';

export default class ModelSearchIndexer {
constructor() {
this.unsubscribers = []
}

modelClass() {
throw new Error("Override me and return a class constructor")
}

configKey() {
throw new Error("Override me and return a string config key")
}

getIndexDataForModel() {
throw new Error("Override me and return a hash with a `content` array")
}

INDEX_VERSION() {
throw new Error("Override me and return an INDEX_VERSION")
}

activate() {
this._initializeIndex();
this.unsubscribers = [
DatabaseStore.listen(this._onDataChanged),
];
}

deactivate() {
this.unsubscribers.forEach(unsub => unsub())
}

_initializeIndex() {
if (NylasEnv.config.get(this.configKey()) !== this.INDEX_VERSION()) {
DatabaseStore.dropSearchIndex(this.modelClass())
.then(() => DatabaseStore.createSearchIndex(this.modelClass()))
.then(() => this._buildIndex())
}
}

_buildIndex(offset = 0) {
const indexingPageSize = 1000;
const indexingPageDelay = 1000;

DatabaseStore.findAll(this.modelClass())
.limit(indexingPageSize)
.offset(offset)
.then((models) => {
if (models.length === 0) {
NylasEnv.config.set(this.configKey(), this.INDEX_VERSION())
return;
}
Promise.each(models, (model) => {
return DatabaseStore.indexModel(model, this.getIndexDataForModel(model))
}).then(() => {
setTimeout(() => {
this._buildIndex(offset + models.length);
}, indexingPageDelay);
});
});
}

/**
* When a model gets updated we will update the search index with the
* data from that model if the account it belongs to is not being
* currently synced.
*/
_onDataChanged = (change) => {
if (change.objectClass !== this.modelClass().name) {
return;
}

change.objects.forEach((model) => {
if (change.type === 'persist') {
DatabaseStore.indexModel(model, this.getIndexDataForModel(model))
} else {
DatabaseStore.unindexModel(model)
}
});
}
}

0 comments on commit e942b91

Please sign in to comment.