Add support for caching Slack profile data in production using Memcached
This commit is contained in:
parent
000977a2c1
commit
8c701a61fa
|
@ -24,7 +24,11 @@
|
||||||
"${workspaceFolder}/index.js"
|
"${workspaceFolder}/index.js"
|
||||||
],
|
],
|
||||||
"env": {
|
"env": {
|
||||||
"DEBUG": "true"
|
"DEBUG": "true",
|
||||||
|
"KUDOS_BOT_CONFIG": "{'options':{'process_whole_history':true},'slack':{'channel_id':'C8P4F6WTB'},'rules':{'tip_per_kudo_in_usd':0.02,'tip_per_reaction_in_usd':0.001,'reaction_threshold':3},'payments':{'STT':{'network_id':'ropsten','private_key':'0xaaaa','contract_address':'0xc55cF4B03948D7EBc8b9E8BAD92643703811d162'},'SNT':{'network_id':'homestead','private_key':'0xaaaa','contract_address':'0x744d70FDBE2Ba4CF95131626614a1763DF805B9E'}}}",
|
||||||
|
"MEMCACHE_URL": "",
|
||||||
|
"MEMCACHE_USERNAME": "",
|
||||||
|
"MEMCACHE_PASSWORD": ""
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -9,13 +9,23 @@
|
||||||
// PombeirP
|
// PombeirP
|
||||||
|
|
||||||
const MemCache = require('mem-cache')
|
const MemCache = require('mem-cache')
|
||||||
const fs = require('fs')
|
const memjs = require('memjs')
|
||||||
const { WebClient } = require('@slack/client')
|
const { WebClient } = require('@slack/client')
|
||||||
|
|
||||||
const token = process.env.SLACK_USER_TOKEN || ''
|
const token = process.env.SLACK_USER_TOKEN || ''
|
||||||
const cachePath = './slack-cache.json'
|
const cacheMemcachedKey = 'slack-profile-cache-json'
|
||||||
var allowLoadFromCache = true
|
var allowLoadFromCache = true
|
||||||
|
|
||||||
|
// Environment variables are defined in app.yaml.
|
||||||
|
let MEMCACHE_URL = process.env.MEMCACHE_URL || '127.0.0.1:11211'
|
||||||
|
if (process.env.USE_GAE_MEMCACHE) {
|
||||||
|
MEMCACHE_URL = `${process.env.GAE_MEMCACHE_HOST}:${process.env.GAE_MEMCACHE_PORT}`
|
||||||
|
}
|
||||||
|
const mc = memjs.Client.create(MEMCACHE_URL, {
|
||||||
|
username: process.env.MEMCACHE_USERNAME,
|
||||||
|
password: process.env.MEMCACHE_PASSWORD
|
||||||
|
})
|
||||||
|
|
||||||
module.exports = (robot) => new GitHubSlackIdMapper(robot)
|
module.exports = (robot) => new GitHubSlackIdMapper(robot)
|
||||||
|
|
||||||
class GitHubSlackIdMapper {
|
class GitHubSlackIdMapper {
|
||||||
|
@ -28,6 +38,15 @@ class GitHubSlackIdMapper {
|
||||||
setInterval(() => internalBuild(this.robot, this.cache), 24 * 60 * 60 * 1000)
|
setInterval(() => internalBuild(this.robot, this.cache), 24 * 60 * 60 * 1000)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async getSlackUsernameFromSlackId (slackUserId) {
|
||||||
|
await this.buildPromise
|
||||||
|
const profile = this.cache.get(getSlackId2ProfileCacheKeyName(slackUserId))
|
||||||
|
if (profile) {
|
||||||
|
return profile.name
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
async getGitHubHandleFromSlackId (slackUserId) {
|
async getGitHubHandleFromSlackId (slackUserId) {
|
||||||
await this.buildPromise
|
await this.buildPromise
|
||||||
const profile = this.cache.get(getSlackId2ProfileCacheKeyName(slackUserId))
|
const profile = this.cache.get(getSlackId2ProfileCacheKeyName(slackUserId))
|
||||||
|
@ -54,13 +73,13 @@ class GitHubSlackIdMapper {
|
||||||
async function internalBuild (robot, cache) {
|
async function internalBuild (robot, cache) {
|
||||||
if (allowLoadFromCache) {
|
if (allowLoadFromCache) {
|
||||||
try {
|
try {
|
||||||
const json = fs.readFileSync(cachePath)
|
const json = await mc.get(cacheMemcachedKey)
|
||||||
if (json) {
|
if (json.value) {
|
||||||
const cacheFromFile = JSON.parse(json)
|
const cacheFromFile = JSON.parse(json.value)
|
||||||
for (const kvp of cacheFromFile) {
|
for (const kvp of cacheFromFile) {
|
||||||
cache.set(kvp.k, kvp.v)
|
cache.set(kvp.k, kvp.v)
|
||||||
}
|
}
|
||||||
robot.log.info(`Read Slack user cache from file (${cache.length} entries)`)
|
robot.log.info(`Read Slack user cache from ${MEMCACHE_URL} (${cache.length} entries)`)
|
||||||
allowLoadFromCache = false
|
allowLoadFromCache = false
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -100,14 +119,14 @@ async function internalBuild (robot, cache) {
|
||||||
robot.log.warn(`No GitHub ID field found in @${username} (${user.id}) profile!`)
|
robot.log.warn(`No GitHub ID field found in @${username} (${user.id}) profile!`)
|
||||||
}
|
}
|
||||||
|
|
||||||
const gitHubUsername = gitHubFieldId && profile.fields && profile.fields[gitHubFieldId] ? profile.fields[gitHubFieldId].value : null
|
const gitHubUsername = gitHubFieldId && profile.fields && profile.fields[gitHubFieldId] ? profile.fields[gitHubFieldId].value.replace('https://github.com/', '') : null
|
||||||
if (gitHubUsername) {
|
if (gitHubUsername) {
|
||||||
usersContainingGitHubInfo = usersContainingGitHubInfo.concat(username)
|
usersContainingGitHubInfo = usersContainingGitHubInfo.concat(username)
|
||||||
} else {
|
} else {
|
||||||
usersMissingGitHubInfo = usersMissingGitHubInfo.concat(username)
|
usersMissingGitHubInfo = usersMissingGitHubInfo.concat(username)
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = { github_handle: gitHubUsername }
|
const data = { name: username, github_handle: gitHubUsername }
|
||||||
|
|
||||||
robot.log.debug(`@${username} (${user.id}) -> ${JSON.stringify(data)}`)
|
robot.log.debug(`@${username} (${user.id}) -> ${JSON.stringify(data)}`)
|
||||||
|
|
||||||
|
@ -144,7 +163,15 @@ async function internalBuild (robot, cache) {
|
||||||
for (const key of cache.keys) {
|
for (const key of cache.keys) {
|
||||||
c.push({ k: key, v: cache.get(key) })
|
c.push({ k: key, v: cache.get(key) })
|
||||||
}
|
}
|
||||||
fs.writeFileSync(cachePath, JSON.stringify(c, null, 2))
|
|
||||||
|
if (mc) {
|
||||||
|
try {
|
||||||
|
await mc.set(cacheMemcachedKey, c, {})
|
||||||
|
robot.log.info(`Saved cache to Memcached`)
|
||||||
|
} catch (error) {
|
||||||
|
robot.log.warn(`Error while saving cache to Memcached: ${error}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
robot.log.error(`Error while populating Slack user ID cache: ${e}`)
|
robot.log.error(`Error while populating Slack user ID cache: ${e}`)
|
||||||
}
|
}
|
||||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -16,6 +16,7 @@
|
||||||
"hashset": "0.0.6",
|
"hashset": "0.0.6",
|
||||||
"jenkins": "^0.20.1",
|
"jenkins": "^0.20.1",
|
||||||
"mem-cache": "0.0.5",
|
"mem-cache": "0.0.5",
|
||||||
|
"memjs": "^1.2.0",
|
||||||
"probot": "^5.0.0",
|
"probot": "^5.0.0",
|
||||||
"probot-config": "^0.1.0",
|
"probot-config": "^0.1.0",
|
||||||
"probot-gpg-status": "^0.5.4",
|
"probot-gpg-status": "^0.5.4",
|
||||||
|
|
Loading…
Reference in New Issue