Align GoChat with Chatwoot frontend contracts

This commit is contained in:
2026-06-13 22:13:32 +08:00
parent 71abf58636
commit d884fdda0a
162 changed files with 9825 additions and 528 deletions
+10 -9
View File
@@ -106,10 +106,6 @@ func Bootstrap(env string) (*App, error) {
workerPool := worker.NewWorkerPool(db)
automation.RegisterActionDeliveryJobs(workerPool, &dbProvider{db: db})
service.RegisterConversationMaintenanceJobs(workerPool, db)
if _, err := service.EnqueueScheduledItemsTrigger(context.Background(), workerPool, time.Now()); err != nil {
applogger.L().Warnf("failed to enqueue initial scheduled item trigger: %v", err)
}
// Step 5: Connect to Redis (ref: Chatwoot config/cable.yml)
rdb, err := NewRedisClient(&cfg.Redis)
@@ -330,6 +326,10 @@ func Bootstrap(env string) (*App, error) {
// Create channel dispatcher for event-driven architecture (ref: Chatwoot Dispatcher)
channelDispatcher := channel.NewDispatcher(workerPool)
service.RegisterConversationMaintenanceJobs(workerPool, db, channelDispatcher)
if _, err := service.EnqueueScheduledItemsTrigger(context.Background(), workerPool, time.Now()); err != nil {
applogger.L().Warnf("failed to enqueue initial scheduled item trigger: %v", err)
}
// P9: AgentBot rule engine services
botRuleService := automation.NewBotRuleService(&dbProvider{db: db})
@@ -649,7 +649,7 @@ func Bootstrap(env string) (*App, error) {
profileService.SetConfirmationMailer(service.NewEnvProfileConfirmationMailer())
// Campaign + AutoAssignment services
campaignInternalSvc := campaign.NewCampaignService(db)
campaignInternalSvc := campaign.NewCampaignService(db, channelDispatcher)
campaignService := service.NewCampaignService(campaignInternalSvc, campaignRepo)
assignmentInternalSvc := autoassignment.NewAssignmentService(db, rdb)
assignmentPolicyService := service.NewAssignmentPolicyService(assignmentPolicyRepo, inboxAssignmentPolicyRepo, assignmentInternalSvc)
@@ -724,6 +724,7 @@ func Bootstrap(env string) (*App, error) {
// Must be created before handlers so the hubTypingAdapter can reference it.
wsHub := ws.NewHubSimple()
wsRelay := wspkg.NewBroadcastRelay(rdb, wsHub)
eventPublisher := wspkg.NewEventPublisher(wsHub, nil, wsRelay)
presenceTracker := wspkg.NewPresenceTracker(rdb, wsRelay)
// Widget service + handler (M11 — WebWidget channel completion)
@@ -735,7 +736,7 @@ func Bootstrap(env string) (*App, error) {
widgetOfflineMessageRepo := repository.NewWidgetOfflineMessageRepo(db)
widgetService := service.NewWidgetService(inboxRepo, contactRepo, contactInboxRepo, conversationRepo, messageRepo, widgetTypingAdapter, widgetThemeConfigRepo, preChatFormRepo, widgetFileUploadRepo, widgetOfflineMessageRepo, inboxMemberRepo, tagRepo, campaignRepo)
widgetService.SetWorkerPool(workerPool)
widgetHandler := widget.NewHandler(widgetService)
widgetHandler := widget.NewHandler(widgetService).WithEventPublisher(eventPublisher)
// Upload: DirectUpload repo + service + handler (account-level + widget direct uploads)
directUploadRepo := repository.NewDirectUploadRepo(db)
@@ -753,7 +754,7 @@ func Bootstrap(env string) (*App, error) {
SAML: v1.NewSAMLHandler(samlService, jwtService, refreshStore, ssoSessionStore, &cfg.SAML),
Account: v1.NewAccountHandler(accountService),
EnterpriseAccount: v1.NewEnterpriseAccountHandler(accountService),
Contact: v1.NewContactHandler(contactService, contactInboxService, contactMergeService, contactNoteService, conversationService).WithContactPresence(presenceTracker),
Contact: v1.NewContactHandler(contactService, contactInboxService, contactMergeService, contactNoteService, conversationService).WithContactPresence(presenceTracker).WithEventPublisher(eventPublisher),
Conversation: v1.NewConversationHandler(conversationService, messageService).WithAuditService(auditService).WithContactPresence(presenceTracker),
Inbox: v1.NewInboxHandler(inboxService).WithAuditService(auditService),
InboxMember: v1.NewInboxMemberHandler(inboxMemberService),
@@ -773,7 +774,7 @@ func Bootstrap(env string) (*App, error) {
EmailWebhook: emailWebhookHandler,
Message: v1.NewMessageHandler(messageService),
Profile: v1.NewProfileHandler(profileService),
Notification: v1.NewNotificationHandler(notificationService),
Notification: v1.NewNotificationHandler(notificationService).WithEventPublisher(eventPublisher),
PlatformApp: v1.NewPlatformAppHandler(platformAppService),
Team: v1.NewTeamHandler(teamService),
CaptainAssistant: v1.NewCaptainAssistantHandler(captainAssistantService),
@@ -845,7 +846,7 @@ func Bootstrap(env string) (*App, error) {
ConversationParticipant: v1.NewConversationParticipantHandler(conversationParticipantService),
DraftMessage: v1.NewDraftMessageHandler(draftMessageService),
// G4: Companies module (CRUD + search + nested contacts/conversations/notes)
Company: v1.NewCompanyHandler(companyService),
Company: v1.NewCompanyHandler(companyService).WithEventPublisher(eventPublisher),
// Custom attributes + custom filters
CustomAttributeDefinition: v1.NewCustomAttributeDefinitionHandler(customAttributeDefinitionService),
CustomAttributeValue: v1.NewCustomAttributeValueHandler(customAttributeValueService),
+7 -3
View File
@@ -7,9 +7,9 @@ import (
"strings"
"time"
"github.com/redis/go-redis/v9"
"github.com/gochat/gochat/internal/config"
"github.com/gochat/gochat/pkg/logger"
"github.com/redis/go-redis/v9"
)
// NewRedisClient creates a Redis client for caching, Pub/Sub, and sessions.
@@ -23,7 +23,11 @@ func NewRedisClient(cfg *config.RedisConfig) (*redis.Client, error) {
if cfg.Password != "" {
opts.Password = cfg.Password
}
opts.PoolSize = 10
poolSize := cfg.PoolSize
if poolSize <= 0 {
poolSize = 50
}
opts.PoolSize = poolSize
client := redis.NewClient(opts)
@@ -35,7 +39,7 @@ func NewRedisClient(cfg *config.RedisConfig) (*redis.Client, error) {
return nil, fmt.Errorf("failed to connect to Redis: %w", err)
}
logger.L().Infof("Connected to Redis: %s (pool=%d)", cfg.URL, 10)
logger.L().Infof("Connected to Redis: %s (pool=%d)", cfg.URL, poolSize)
return client, nil
}