search.js 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import loggerFactory from '~/utils/logger';
  2. // eslint-disable-next-line no-unused-vars
  3. const logger = loggerFactory('growi:service:search');
  4. class SearchService {
  5. constructor(crowi) {
  6. this.crowi = crowi;
  7. this.configManager = crowi.configManager;
  8. this.isErrorOccuredOnHealthcheck = null;
  9. this.isErrorOccuredOnSearching = null;
  10. try {
  11. this.delegator = this.generateDelegator();
  12. }
  13. catch (err) {
  14. logger.error(err);
  15. }
  16. if (this.isConfigured) {
  17. this.delegator.init();
  18. this.registerUpdateEvent();
  19. }
  20. }
  21. get isConfigured() {
  22. return this.delegator != null;
  23. }
  24. get isReachable() {
  25. return this.isConfigured && !this.isErrorOccuredOnHealthcheck && !this.isErrorOccuredOnSearching;
  26. }
  27. get isSearchboxEnabled() {
  28. const uri = this.configManager.getConfig('crowi', 'app:searchboxSslUrl');
  29. return uri != null && uri.length > 0;
  30. }
  31. get isElasticsearchEnabled() {
  32. const uri = this.configManager.getConfig('crowi', 'app:elasticsearchUri');
  33. return uri != null && uri.length > 0;
  34. }
  35. generateDelegator() {
  36. logger.info('Initializing search delegator');
  37. if (this.isSearchboxEnabled) {
  38. const SearchboxDelegator = require('./search-delegator/searchbox');
  39. logger.info('Searchbox is enabled');
  40. return new SearchboxDelegator(this.configManager, this.crowi.socketIoService);
  41. }
  42. if (this.isElasticsearchEnabled) {
  43. const ElasticsearchDelegator = require('./search-delegator/elasticsearch');
  44. logger.info('Elasticsearch (not Searchbox) is enabled');
  45. return new ElasticsearchDelegator(this.configManager, this.crowi.socketIoService);
  46. }
  47. logger.info('No elasticsearch URI is specified so that full text search is disabled.');
  48. }
  49. registerUpdateEvent() {
  50. const pageEvent = this.crowi.event('page');
  51. pageEvent.on('create', this.delegator.syncPageUpdated.bind(this.delegator));
  52. pageEvent.on('update', this.delegator.syncPageUpdated.bind(this.delegator));
  53. pageEvent.on('deleteCompletely', this.delegator.syncPagesDeletedCompletely.bind(this.delegator));
  54. pageEvent.on('delete', this.delegator.syncPageDeleted.bind(this.delegator));
  55. pageEvent.on('updateMany', this.delegator.syncPagesUpdated.bind(this.delegator));
  56. pageEvent.on('syncDescendants', this.delegator.syncDescendantsPagesUpdated.bind(this.delegator));
  57. const bookmarkEvent = this.crowi.event('bookmark');
  58. bookmarkEvent.on('create', this.delegator.syncBookmarkChanged.bind(this.delegator));
  59. bookmarkEvent.on('delete', this.delegator.syncBookmarkChanged.bind(this.delegator));
  60. const tagEvent = this.crowi.event('tag');
  61. tagEvent.on('update', this.delegator.syncTagChanged.bind(this.delegator));
  62. }
  63. resetErrorStatus() {
  64. this.isErrorOccuredOnHealthcheck = false;
  65. this.isErrorOccuredOnSearching = false;
  66. }
  67. async reconnectClient() {
  68. logger.info('Try to reconnect...');
  69. this.delegator.initClient();
  70. try {
  71. await this.getInfoForHealth();
  72. logger.info('Reconnecting succeeded.');
  73. this.resetErrorStatus();
  74. }
  75. catch (err) {
  76. throw err;
  77. }
  78. }
  79. async getInfo() {
  80. try {
  81. return await this.delegator.getInfo();
  82. }
  83. catch (err) {
  84. logger.error(err);
  85. throw err;
  86. }
  87. }
  88. async getInfoForHealth() {
  89. try {
  90. const result = await this.delegator.getInfoForHealth();
  91. this.isErrorOccuredOnHealthcheck = false;
  92. return result;
  93. }
  94. catch (err) {
  95. logger.error(err);
  96. // switch error flag, `isErrorOccuredOnHealthcheck` to be `false`
  97. this.isErrorOccuredOnHealthcheck = true;
  98. throw err;
  99. }
  100. }
  101. async getInfoForAdmin() {
  102. return this.delegator.getInfoForAdmin();
  103. }
  104. async normalizeIndices() {
  105. return this.delegator.normalizeIndices();
  106. }
  107. async rebuildIndex() {
  108. return this.delegator.rebuildIndex();
  109. }
  110. async searchKeyword(keyword, user, userGroups, searchOpts) {
  111. try {
  112. return await this.delegator.searchKeyword(keyword, user, userGroups, searchOpts);
  113. }
  114. catch (err) {
  115. logger.error(err);
  116. // switch error flag, `isReachable` to be `false`
  117. this.isErrorOccuredOnSearching = true;
  118. throw err;
  119. }
  120. }
  121. }
  122. module.exports = SearchService;