Просмотр исходного кода

Merge pull request #1183 from weseek/imprv/1162-es-alias

Imprv/1162 es alias
Yuki Takei 6 лет назад
Родитель
Сommit
b75d186ab9
3 измененных файлов с 95 добавлено и 50 удалено
  1. 10 11
      src/server/crowi/index.js
  2. 2 26
      src/server/routes/admin.js
  3. 83 13
      src/server/util/search.js

+ 10 - 11
src/server/crowi/index.js

@@ -321,18 +321,17 @@ Crowi.prototype.setupSearcher = async function() {
   const searcherUri = this.env.ELASTICSEARCH_URI
     || this.env.BONSAI_URL
     || null;
-  return new Promise(((resolve, reject) => {
-    if (searcherUri) {
-      try {
-        self.searcher = new (require(path.join(self.libDir, 'util', 'search')))(self, searcherUri);
-      }
-      catch (e) {
-        logger.error('Error on setup searcher', e);
-        self.searcher = null;
-      }
+
+  if (searcherUri) {
+    try {
+      self.searcher = new (require(path.join(self.libDir, 'util', 'search')))(self, searcherUri);
+      self.searcher.initIndices();
     }
-    resolve();
-  }));
+    catch (e) {
+      logger.error('Error on setup searcher', e);
+      self.searcher = null;
+    }
+  }
 };
 
 Crowi.prototype.setupMailer = async function() {

+ 2 - 26
src/server/routes/admin.js

@@ -1366,38 +1366,14 @@ module.exports = function(crowi, app) {
       return res.json(ApiResponse.error('ElasticSearch Integration is not set up.'));
     }
 
-    // first, delete index
-    try {
-      await search.deleteIndex();
-    }
-    catch (err) {
-      logger.warn('Delete index Error, but if it is initialize, its ok.', err);
-    }
-
-    // second, create index
-    try {
-      await search.buildIndex();
-    }
-    catch (err) {
-      logger.error('Error', err);
-      return res.json(ApiResponse.error(err));
-    }
-
     searchEvent.on('addPageProgress', (total, current, skip) => {
       crowi.getIo().sockets.emit('admin:addPageProgress', { total, current, skip });
     });
     searchEvent.on('finishAddPage', (total, current, skip) => {
       crowi.getIo().sockets.emit('admin:finishAddPage', { total, current, skip });
     });
-    // add all page
-    search
-      .addAllPages()
-      .then(() => {
-        debug('Data is successfully indexed. ------------------ ✧✧');
-      })
-      .catch((err) => {
-        logger.error('Error', err);
-      });
+
+    await search.buildIndex();
 
     return res.json(ApiResponse.success());
   };

+ 83 - 13
src/server/util/search.js

@@ -44,6 +44,7 @@ function SearchClient(crowi, esUri) {
   const uri = this.parseUri(this.esUri);
   this.host = uri.host;
   this.indexName = uri.indexName;
+  this.aliasName = `${this.indexName}-alias`;
 
   this.client = new elasticsearch.Client({
     host: this.host,
@@ -117,17 +118,86 @@ SearchClient.prototype.parseUri = function(uri) {
   };
 };
 
-SearchClient.prototype.buildIndex = function(uri) {
-  return this.client.indices.create({
-    index: this.indexName,
-    body: require(this.mappingFile),
-  });
+SearchClient.prototype.initIndices = async function() {
+  await this.checkESVersion();
+
+  const { client, indexName, aliasName } = this;
+
+  const tmpIndexName = `${indexName}-tmp`;
+
+  // remove tmp index
+  const isExistsTmpIndex = await client.indices.exists({ index: tmpIndexName });
+  if (isExistsTmpIndex) {
+    await client.indices.delete({ index: tmpIndexName });
+  }
+
+  // create index
+  const isExistsIndex = await client.indices.exists({ index: indexName });
+  if (!isExistsIndex) {
+    await this.createIndex(indexName);
+  }
+
+  // create alias
+  const isExistsAlias = await client.indices.existsAlias({ name: aliasName, index: indexName });
+  if (!isExistsAlias) {
+    await client.indices.putAlias({
+      name: aliasName,
+      index: indexName,
+    });
+  }
 };
 
-SearchClient.prototype.deleteIndex = function(uri) {
-  return this.client.indices.delete({
-    index: this.indexName,
+SearchClient.prototype.createIndex = async function(index) {
+  const body = require(this.mappingFile);
+  return this.client.indices.create({ index, body });
+};
+
+SearchClient.prototype.buildIndex = async function(uri) {
+  await this.initIndices();
+
+  const { client, indexName } = this;
+
+  const aliasName = `${indexName}-alias`;
+  const tmpIndexName = `${indexName}-tmp`;
+
+  // reindex to tmp index
+  await this.createIndex(tmpIndexName);
+  await client.reindex({
+    body: {
+      source: { index: indexName },
+      dest: { index: tmpIndexName },
+    },
+  });
+
+  // update alias
+  await client.indices.updateAliases({
+    body: {
+      actions: [
+        { add: { alias: aliasName, index: tmpIndexName } },
+        { remove: { alias: aliasName, index: indexName } },
+      ],
+    },
   });
+
+  // flush index
+  await client.indices.delete({
+    index: indexName,
+  });
+  await this.createIndex(indexName);
+  await this.addAllPages();
+
+  // update alias
+  await client.indices.updateAliases({
+    body: {
+      actions: [
+        { add: { alias: aliasName, index: indexName } },
+        { remove: { alias: aliasName, index: tmpIndexName } },
+      ],
+    },
+  });
+
+  // remove tmp index
+  await client.indices.delete({ index: tmpIndexName });
 };
 
 /**
@@ -162,7 +232,7 @@ SearchClient.prototype.prepareBodyForUpdate = function(body, page) {
 
   const command = {
     update: {
-      _index: this.indexName,
+      _index: this.aliasName,
       _type: 'pages',
       _id: page._id.toString(),
     },
@@ -194,7 +264,7 @@ SearchClient.prototype.prepareBodyForCreate = function(body, page) {
 
   const command = {
     index: {
-      _index: this.indexName,
+      _index: this.aliasName,
       _type: 'pages',
       _id: page._id.toString(),
     },
@@ -226,7 +296,7 @@ SearchClient.prototype.prepareBodyForDelete = function(body, page) {
 
   const command = {
     delete: {
-      _index: this.indexName,
+      _index: this.aliasName,
       _type: 'pages',
       _id: page._id.toString(),
     },
@@ -399,7 +469,7 @@ SearchClient.prototype.createSearchQuerySortedByUpdatedAt = function(option) {
 
   // default is only id field, sorted by updated_at
   const query = {
-    index: this.indexName,
+    index: this.aliasName,
     type: 'pages',
     body: {
       sort: [{ updated_at: { order: 'desc' } }],
@@ -420,7 +490,7 @@ SearchClient.prototype.createSearchQuerySortedByScore = function(option) {
 
   // sort by score
   const query = {
-    index: this.indexName,
+    index: this.aliasName,
     type: 'pages',
     body: {
       sort: [{ _score: { order: 'desc' } }],