All files / service config.js

57.5% Statements 23/40
25% Branches 3/12
87.5% Functions 7/8
60.53% Lines 23/38

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 8815x 15x 15x       15x 15x   15x             15x       15x 15x 15x         17x     17x 1x   17x 16x         67x       2x 2x           2x 2x       15x   15x                                                         15x  
const debug = require('debug')('crowi:service:config')
const uuidv4 = require('uuid/v4')
const redis = require('redis')
 
class Config {
  constructor(crowi) {
    this.crowi = crowi
    this.config = {}
 
    this.pubSub = {
      id: uuidv4(),
      publisher: null,
      subscriber: null,
      channel: 'config',
    }
 
    this.setupPubSub()
  }
 
  async load() {
    const Config = this.crowi.model('Config')
    const config = await Config.loadAllConfig()
    this.set(config)
  }
 
  set(config) {
    // FIXME: Deep copy to avoid deleting itself.
    config = JSON.parse(JSON.stringify(config))
    // FIXME: Treat as a mutable object always.
    //        We should always get config using `crowi.getConfig()` *just before* referencing config.
    for (const key of Object.keys(this.config)) {
      delete this.config[key]
    }
    for (const key of Object.keys(config)) {
      this.config[key] = config[key]
    }
  }
 
  get() {
    return this.config || {}
  }
 
  notifyUpdated() {
    const { publisher, channel, id } = this.pubSub
    Iif (publisher) {
      publisher.publish(channel, JSON.stringify({ id }))
    }
  }
 
  update(config) {
    this.set(config)
    this.notifyUpdated(config)
  }
 
  setupPubSub() {
    const { redisOpts } = this.crowi
 
    Iif (redisOpts) {
      this.pubSub.publisher = redis.createClient(redisOpts)
      this.pubSub.subscriber = redis.createClient(redisOpts)
 
      const { pubSub } = this
      const { subscriber } = pubSub
 
      debug('PubSubId', pubSub.id)
 
      if (subscriber) {
        subscriber.on('message', async (channel, message) => {
          if (channel !== pubSub.channel) return
 
          const { id } = JSON.parse(message)
          if (id === pubSub.id) return
 
          await this.load()
 
          await Promise.all([this.crowi.setupSlack(), this.crowi.setupMailer()])
 
          debug(`Config updated by ${pubSub.id}`)
        })
 
        subscriber.subscribe(pubSub.channel)
      }
    }
  }
}
 
module.exports = Config