Files
libredesk/internal/automation/automation.go
2024-07-01 03:08:45 +05:30

117 lines
2.5 KiB
Go

package automation
import (
"context"
"embed"
"encoding/json"
"github.com/abhinavxd/artemis/internal/automation/models"
cmodels "github.com/abhinavxd/artemis/internal/conversation/models"
"github.com/abhinavxd/artemis/internal/dbutil"
"github.com/jmoiron/sqlx"
"github.com/zerodha/logf"
)
var (
//go:embed queries.sql
efs embed.FS
)
type Engine struct {
q queries
lo *logf.Logger
conversationStore ConversationStore
messageStore MessageStore
rules []models.Rule
conversationQ chan cmodels.Conversation
}
type Opts struct {
DB *sqlx.DB
Lo *logf.Logger
}
type ConversationStore interface {
UpdateTeamAssignee(uuid string, assigneeUUID []byte) error
UpdateStatus(uuid string, status []byte) error
}
type MessageStore interface {
RecordAssigneeTeamChange(convUUID, value, actorUUID string) error
RecordStatusChange(updatedValue, convUUID, actorUUID string) error
}
type queries struct {
GetRules *sqlx.Stmt `query:"get-rules"`
}
func New(opt Opts) (*Engine, error) {
var (
q queries
e = &Engine{
lo: opt.Lo,
conversationQ: make(chan cmodels.Conversation, 10000),
}
)
if err := dbutil.ScanSQLFile("queries.sql", &q, opt.DB, efs); err != nil {
return nil, err
}
e.q = q
e.rules = e.getRules()
return e, nil
}
func (e *Engine) ReloadRules() {
e.rules = e.getRules()
}
func (e *Engine) SetMessageStore(messageStore MessageStore) {
e.messageStore = messageStore
}
func (e *Engine) SetConversationStore(conversationStore ConversationStore) {
e.conversationStore = conversationStore
}
func (e *Engine) Serve(ctx context.Context) {
for {
select {
case <-ctx.Done():
return
case conversation := <-e.conversationQ:
e.processConversations(conversation)
}
}
}
func (e *Engine) EvaluateRules(c cmodels.Conversation) {
select {
case e.conversationQ <- c:
default:
// Queue is full.
e.lo.Warn("EvaluateRules: conversationQ is full, unable to enqueue conversation")
}
}
func (e *Engine) getRules() []models.Rule {
var rulesJSON []string
err := e.q.GetRules.Select(&rulesJSON)
if err != nil {
e.lo.Error("error fetching automation rules", "error", err)
return nil
}
var rules []models.Rule
for _, ruleJSON := range rulesJSON {
var rulesBatch []models.Rule
if err := json.Unmarshal([]byte(ruleJSON), &rulesBatch); err != nil {
e.lo.Error("error unmarshalling rule JSON", "error", err)
continue
}
rules = append(rules, rulesBatch...)
}
e.lo.Debug("fetched rules", "num", len(rules), "rules", rules)
return rules
}