projeto-hit/backend/src/helpers/TicketCache.ts

426 lines
9.8 KiB
TypeScript
Raw Normal View History

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 () => {
if(!process.env.CACHE){
return null
}
try {
const redis = new Redis();
const conn = () => new Promise((resolve, reject) => {
redis.on('error', (err) => {
if (err.code === 'ECONNREFUSED') {
console.error(`Redis connection error: ${err}.`)
redis.quit()
}
else {
console.error(`Redis encountered an error: ${err.message}.`)
}
reject(err)
})
redis.on('connect', () => {
resolve(redis);
})
});
return await conn();
} catch (e) {
console.error(e);
return Promise.resolve([]);
}
}
const flushCache = async () => {
const redis: any = await redisConn();
if(!redis) return false
if (redis.status === 'connect') {
console.log('TICKETS CACHE REMOVED')
await redis.call('FLUSHALL')
redis.quit()
}
}
const cacheSize = async () => {
const redis: any = await redisConn();
if(!redis) return null
if (redis.status !== 'connect') {
return -1
}
const size = await redis.call('dbsize')
redis.quit()
return size
}
const loadTicketsCache = async () => {
const redis: any = await redisConn();
if(!redis) return
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!`) });
redis.quit()
}
const createTicketIndexCache = async (hashIndex: string) => {
const redis: any = await redisConn();
if(!redis) return
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)
}
redis.quit()
}
const updateTicketCache = async (hash: any, json_object: any) => {
const redis: any = await redisConn();
if(!redis) return
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") });
redis.quit()
}
const updateTicketCacheByTicketId = async (ticketId: string | number, update_fields: any) => {
const redis: any = await redisConn();
if(!redis) return
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}`)
}
redis.quit()
}
const createOrUpdateTicketCache = async (hash: any, ticket: any) => {
const redis: any = await redisConn();
if(!redis) return
if (redis.status !== 'connect') return
if (redis.status !== 'connect') return
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')
redis.quit()
}
const deleteTicketsByIdCache = async (ticketId: string | number) => {
const redis: any = await redisConn();
if(!redis) return
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}`)
}
redis.quit()
}
const deleteTicketsFieldsCache = async (tickets: any, del_fields: any) => {
const redis: any = await redisConn();
if(!redis) return
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)
}
}
redis.quit()
}
const updateTicketsByContactsCache = async (oldNumber: string, newName: string, newNumber: string) => {
const redis: any = await redisConn();
if(!redis) return
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)
}
}
redis.quit()
}
const deleteTicketsByContactsCache = async (number: string) => {
const redis: any = await redisConn();
if(!redis) return
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)
}
}
redis.quit()
}
const deleteTicketCache = async (hash: any) => {
const redis: any = await redisConn();
if(!redis) return
if (redis.status !== 'connect') return
await redis.del(hash)
redis.quit()
}
async function searchTicketCache(search: string, offset?: number, limit?: number) {
const redis:any = await redisConn();
if(!redis) return
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}*)`)
}
redis.quit()
// 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
}