2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
import Redis from 'ioredis'
|
|
|
|
import { List } from 'whatsapp-web.js'
|
|
|
|
const unflatten = require('flat').unflatten
|
|
|
|
var flatten = require('flat')
|
|
|
|
import ListTicketServiceCache from "../services/TicketServices/ListTicketServiceCache"
|
|
|
|
|
|
|
|
import { escapeCharCache } from './ContactsCache'
|
|
|
|
|
|
|
|
|
|
|
|
const redisConn = async () => {
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!process.env.CACHE){
|
|
|
|
return null
|
|
|
|
}
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const redis = new Redis();
|
|
|
|
|
|
|
|
const conn = () => new Promise((resolve, reject) => {
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
redis.on('error', async (err) => {
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
if (err.code === 'ECONNREFUSED') {
|
|
|
|
console.error(`Redis connection error: ${err}.`)
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.error(`Redis encountered an error: ${err.message}.`)
|
|
|
|
}
|
|
|
|
|
|
|
|
reject(err)
|
|
|
|
|
|
|
|
})
|
|
|
|
|
|
|
|
redis.on('connect', () => {
|
|
|
|
|
2022-12-23 22:45:18 +00:00
|
|
|
// console.log('CacheStore - Connection status: connected');
|
2022-10-25 14:16:36 +00:00
|
|
|
resolve(redis);
|
|
|
|
|
|
|
|
})
|
2022-12-23 22:45:18 +00:00
|
|
|
|
|
|
|
redis.on('end', () => {
|
|
|
|
// console.log('CacheStore - Connection status: disconnected');
|
|
|
|
});
|
|
|
|
|
|
|
|
redis.on('reconnecting', () => {
|
|
|
|
// console.log('CacheStore - Connection status: reconnecting');
|
|
|
|
});
|
2022-10-25 14:16:36 +00:00
|
|
|
});
|
|
|
|
|
|
|
|
return await conn();
|
|
|
|
|
|
|
|
} catch (e) {
|
|
|
|
console.error(e);
|
|
|
|
return Promise.resolve([]);
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const flushCache = async () => {
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
const redis: any = await redisConn();
|
|
|
|
|
|
|
|
if(!redis) return false
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
if (redis.status === 'connect') {
|
|
|
|
|
|
|
|
console.log('TICKETS CACHE REMOVED')
|
|
|
|
await redis.call('FLUSHALL')
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const cacheSize = async () => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
if(!redis) return null
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') {
|
|
|
|
return -1
|
|
|
|
}
|
|
|
|
|
|
|
|
const size = await redis.call('dbsize')
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
return size
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const loadTicketsCache = async () => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
await createTicketIndexCache('idx_ticket')
|
|
|
|
|
|
|
|
let tickets = await ListTicketServiceCache({})
|
|
|
|
|
|
|
|
const pipeline = redis.pipeline()
|
|
|
|
|
|
|
|
for (let i = 0; i < tickets.length; i++) {
|
|
|
|
|
|
|
|
tickets[i].createdAt = new Date(tickets[i].createdAt).toISOString()
|
|
|
|
tickets[i].updatedAt = new Date(tickets[i].updatedAt).toISOString()
|
|
|
|
|
|
|
|
tickets[i].escaped_name = escapeCharCache(tickets[i]['contact.name'])
|
|
|
|
|
|
|
|
// tickets[i]['contact_name'] = tickets[i]['contact.name']
|
|
|
|
// delete tickets[i]['contact.name']
|
|
|
|
|
|
|
|
tickets[i]['contact_number'] = tickets[i]['contact.number']
|
|
|
|
delete tickets[i]['contact.number']
|
|
|
|
|
|
|
|
pipeline.hmset(`ticket:${tickets[i].id}`, tickets[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
await pipeline.exec(() => { console.log(`${tickets.length} TICKETS INSERTED IN CACHE!`) });
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const createTicketIndexCache = async (hashIndex: string) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
try {
|
|
|
|
|
|
|
|
const lst_index_redis: any = await redis.call('FT._LIST')
|
|
|
|
|
|
|
|
if (lst_index_redis.includes(hashIndex)) {
|
|
|
|
console.log('entrou...')
|
|
|
|
await redis.call('FT.DROPINDEX', hashIndex)
|
|
|
|
}
|
|
|
|
|
|
|
|
const response = await redis.call('FT.CREATE', hashIndex, 'ON', 'HASH', 'PREFIX', '1', 'ticket:', 'SCHEMA', 'escaped_name', 'TEXT', 'SORTABLE', 'contact_number', 'TEXT', 'SORTABLE', 'status', 'TAG', 'SORTABLE')
|
|
|
|
|
|
|
|
console.log('Ticket index created: ', response)
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error on createTicketIndexCache: ', error)
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
const updateTicketCache = async (hash: any, json_object: any) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const pipeline = redis.pipeline()
|
|
|
|
let entries = Object.entries(json_object)
|
|
|
|
|
|
|
|
entries.forEach((e: any) => {
|
|
|
|
pipeline.hset(hash, e[0], e[1])
|
|
|
|
})
|
|
|
|
|
|
|
|
await pipeline.exec(() => { console.log("updateTicketCache Key/value inserted/updated") });
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const updateTicketCacheByTicketId = async (ticketId: string | number, update_fields: any) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const ticket_cache = await redis.hgetall(`ticket:${ticketId}`)
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (ticket_cache && Object.keys(ticket_cache).length > 0) {
|
|
|
|
|
|
|
|
if (update_fields.escaped_name) {
|
|
|
|
update_fields.escaped_name = escapeCharCache(update_fields['contact.name'])
|
|
|
|
}
|
|
|
|
|
|
|
|
await updateTicketCache(`ticket:${ticketId}`, update_fields)
|
|
|
|
|
|
|
|
console.log(`updateTicketCacheByTicketId TICKET ${ticket_cache['contact_number']} CACHE WAS UPDATED!`)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.log('TICKET CACHE NOT FOUND!')
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.log(`There was an error on updateTicketCacheByTicketId: ${error}`)
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const createOrUpdateTicketCache = async (hash: any, ticket: any) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-11-14 14:21:58 +00:00
|
|
|
if (redis.status !== 'connect') return
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
ticket.escaped_name = escapeCharCache(ticket['contact.name'])
|
|
|
|
|
|
|
|
ticket['contact_number'] = ticket['contact.number']
|
|
|
|
delete ticket['contact.number']
|
|
|
|
|
|
|
|
await redis.hmset(hash, ticket);
|
|
|
|
|
|
|
|
console.log('CREATED/UPDATED TICKET CACHE')
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const deleteTicketsByIdCache = async (ticketId: string | number) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const ticket_cache = await redis.hgetall(`ticket:${ticketId}`)
|
|
|
|
|
|
|
|
try {
|
|
|
|
if (ticket_cache && Object.keys(ticket_cache).length > 0) {
|
|
|
|
|
|
|
|
await redis.del(`ticket:${ticketId}`)
|
|
|
|
|
|
|
|
console.log(`TICKET ${ticket_cache['id']} CACHE WAS DELETED!`)
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
console.log('TICKET CACHE NOT FOUND!')
|
|
|
|
}
|
|
|
|
} catch (error) {
|
|
|
|
console.log(`There was an error on deleteTicketsByIdCache: ${error}`)
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const deleteTicketsFieldsCache = async (tickets: any, del_fields: any) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const pipeline = redis.pipeline()
|
|
|
|
|
|
|
|
if (tickets && tickets.length > 0) {
|
|
|
|
try {
|
|
|
|
|
|
|
|
for (let i = 0; i < tickets.length; i++) {
|
|
|
|
|
|
|
|
pipeline.hdel(`ticket:${tickets[i]['id']}`, del_fields)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
await pipeline.exec(() => { console.log(`Tickets cache contact updated!`) })
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error on deleteTicketsFieldsByContactsCache function: ', error)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const updateTicketsByContactsCache = async (oldNumber: string, newName: string, newNumber: string) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const pipeline = redis.pipeline()
|
|
|
|
|
|
|
|
const tickets = await searchTicketCache(oldNumber)
|
|
|
|
|
|
|
|
if (tickets && tickets.length > 0) {
|
|
|
|
try {
|
|
|
|
for (let i = 0; i < tickets.length; i++) {
|
|
|
|
|
|
|
|
tickets[i]['contact.name'] = newName
|
|
|
|
tickets[i].escaped_name = escapeCharCache(newName)
|
|
|
|
tickets[i]['contact_number'] = newNumber
|
|
|
|
|
|
|
|
pipeline.hmset(`ticket:${tickets[i]['id']}`, tickets[i])
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
await pipeline.exec(() => { console.log(`updateTicketsByContactsCache Tickets cache contact updated!`) })
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error on updateTicketsByContactsCache function: ', error)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
const deleteTicketsByContactsCache = async (number: string) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
const pipeline = redis.pipeline()
|
|
|
|
|
|
|
|
const tickets = await searchTicketCache(number)
|
|
|
|
|
|
|
|
if (tickets && tickets.length > 0) {
|
|
|
|
try {
|
|
|
|
for (let i = 0; i < tickets.length; i++) {
|
|
|
|
|
|
|
|
pipeline.del(`ticket:${tickets[i]['id']}`)
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
await pipeline.exec(() => { console.log(`Tickets cache number ${tickets[0]['contact_number']} deleted!`) })
|
|
|
|
|
|
|
|
} catch (error) {
|
|
|
|
console.log('There was an error on deleteTicketsByContactsCache function: ', error)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
const deleteTicketCache = async (hash: any) => {
|
|
|
|
|
|
|
|
const redis: any = await redisConn();
|
2022-11-08 23:16:39 +00:00
|
|
|
|
|
|
|
if(!redis) return
|
|
|
|
|
2022-10-25 14:16:36 +00:00
|
|
|
if (redis.status !== 'connect') return
|
|
|
|
|
|
|
|
await redis.del(hash)
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
async function searchTicketCache(search: string, offset?: number, limit?: number) {
|
|
|
|
|
2022-11-08 23:16:39 +00:00
|
|
|
const redis:any = await redisConn();
|
|
|
|
|
|
|
|
if(!redis) return
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
if(redis.status!=='connect') return null
|
|
|
|
|
|
|
|
search = escapeCharCache(search)
|
|
|
|
|
|
|
|
let response: any = undefined
|
|
|
|
|
|
|
|
if (offset != undefined && limit != undefined) {
|
|
|
|
response = await redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`, 'LIMIT', offset, limit, 'SORTBY', 'status', 'DESC')
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
response = await redis.call('FT.SEARCH', 'idx_ticket', `(@escaped_name:*${search}*)|(@contact_number:*${search}*)`)
|
|
|
|
}
|
2022-12-23 19:27:14 +00:00
|
|
|
await redis.quit()
|
2022-10-25 14:16:36 +00:00
|
|
|
|
|
|
|
// console.log('response: ', response)
|
|
|
|
|
|
|
|
if (response.length === 1) {
|
|
|
|
return []
|
|
|
|
}
|
|
|
|
|
|
|
|
const results: any = []
|
|
|
|
|
|
|
|
for (let n = 2; n < response.length; n += 2) {
|
|
|
|
const result: any = {}
|
|
|
|
const fieldNamesAndValues = response[n]
|
|
|
|
|
|
|
|
for (let m = 0; m < fieldNamesAndValues.length; m += 2) {
|
|
|
|
const k = fieldNamesAndValues[m]
|
|
|
|
const v = fieldNamesAndValues[m + 1]
|
|
|
|
result[k] = v
|
|
|
|
}
|
|
|
|
|
|
|
|
results.push(result)
|
|
|
|
}
|
|
|
|
|
|
|
|
return results
|
|
|
|
}
|
|
|
|
|
|
|
|
export {
|
|
|
|
loadTicketsCache,
|
|
|
|
updateTicketCache,
|
|
|
|
createOrUpdateTicketCache,
|
|
|
|
searchTicketCache,
|
|
|
|
updateTicketCacheByTicketId,
|
|
|
|
deleteTicketsByContactsCache,
|
|
|
|
updateTicketsByContactsCache,
|
|
|
|
deleteTicketsByIdCache,
|
|
|
|
flushCache,
|
|
|
|
deleteTicketsFieldsCache,
|
|
|
|
cacheSize,
|
|
|
|
redisConn
|
|
|
|
}
|