feat: add kafka admin integration
This commit is contained in:
+115
-2
@@ -151,6 +151,7 @@ const (
|
||||
type TenantsPersistenceInterface interface {
|
||||
GetByCode(code string) (*types.Tenant, error)
|
||||
GetByID(id types.TenantID) (*types.Tenant, error)
|
||||
ListActive(limit int) ([]types.Tenant, error)
|
||||
}
|
||||
|
||||
type tenantsMapper struct{}
|
||||
@@ -158,6 +159,22 @@ type tenantsMapper struct{}
|
||||
// Tenants is the tenant registry access object.
|
||||
var Tenants TenantsPersistenceInterface
|
||||
|
||||
// AdminInternalConfigProvider optionally resolves hotgo-owned configuration
|
||||
// through the Admin service instead of reading the hotgo database directly.
|
||||
type AdminInternalConfigProvider interface {
|
||||
GetTenantByCode(code string) (*types.Tenant, error)
|
||||
GetTenantByID(id types.TenantID) (*types.Tenant, error)
|
||||
ListActiveTenants(limit int) ([]types.Tenant, error)
|
||||
RegistrationSMSEnabled() (bool, error)
|
||||
ThirdPartyConfig(group string, keys ...string) (map[string]string, error)
|
||||
}
|
||||
|
||||
var adminInternalConfigProvider AdminInternalConfigProvider
|
||||
|
||||
func SetAdminInternalConfigProvider(provider AdminInternalConfigProvider) {
|
||||
adminInternalConfigProvider = provider
|
||||
}
|
||||
|
||||
// RegistrationConfigPersistenceInterface exposes global registration policy.
|
||||
type RegistrationConfigPersistenceInterface interface {
|
||||
SMSEnabled() (bool, error)
|
||||
@@ -172,6 +189,14 @@ func (registrationConfigMapper) SMSEnabled() (bool, error) {
|
||||
if enabled, ok := registrationSMSCache.get("im:register_sms_enabled"); ok {
|
||||
return enabled, nil
|
||||
}
|
||||
if adminInternalConfigProvider != nil {
|
||||
if enabled, err := adminInternalConfigProvider.RegistrationSMSEnabled(); err == nil {
|
||||
registrationSMSCache.set("im:register_sms_enabled", enabled)
|
||||
return enabled, nil
|
||||
} else {
|
||||
logs.Warn.Printf("admin internal registration config fallback failed: %v", err)
|
||||
}
|
||||
}
|
||||
configAdp, ok := adp.(adapter.RegistrationConfigAdapter)
|
||||
if !ok {
|
||||
return true, types.ErrUnsupported
|
||||
@@ -198,6 +223,14 @@ func (thirdPartyConfigMapper) Get(group string, keys ...string) (map[string]stri
|
||||
if cached, ok := thirdPartyConfigCache.get(cacheKey); ok {
|
||||
return cloneStringMap(cached), nil
|
||||
}
|
||||
if adminInternalConfigProvider != nil {
|
||||
if result, err := adminInternalConfigProvider.ThirdPartyConfig(group, keys...); err == nil {
|
||||
thirdPartyConfigCache.set(cacheKey, cloneStringMap(result))
|
||||
return result, nil
|
||||
} else {
|
||||
logs.Warn.Printf("admin internal third-party config fallback failed: group=%s err=%v", group, err)
|
||||
}
|
||||
}
|
||||
configAdp, ok := adp.(adapter.ThirdPartyConfigAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
@@ -261,6 +294,15 @@ func (tenantsMapper) GetByCode(code string) (*types.Tenant, error) {
|
||||
if tenant, ok := tenantByCodeCache.get(code); ok {
|
||||
return cloneTenant(tenant), nil
|
||||
}
|
||||
if adminInternalConfigProvider != nil {
|
||||
if tenant, err := adminInternalConfigProvider.GetTenantByCode(code); err == nil && tenant != nil {
|
||||
tenantByCodeCache.set(code, cloneTenant(tenant))
|
||||
tenantByIDCache.set(strconv.FormatInt(int64(tenant.ID), 10), cloneTenant(tenant))
|
||||
return tenant, nil
|
||||
} else if err != nil {
|
||||
logs.Warn.Printf("admin internal tenant by code fallback failed: code=%s err=%v", code, err)
|
||||
}
|
||||
}
|
||||
tenantAdp, ok := adp.(adapter.TenantAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
@@ -282,6 +324,15 @@ func (tenantsMapper) GetByID(id types.TenantID) (*types.Tenant, error) {
|
||||
if tenant, ok := tenantByIDCache.get(idKey); ok {
|
||||
return cloneTenant(tenant), nil
|
||||
}
|
||||
if adminInternalConfigProvider != nil {
|
||||
if tenant, err := adminInternalConfigProvider.GetTenantByID(id); err == nil && tenant != nil {
|
||||
tenantByIDCache.set(idKey, cloneTenant(tenant))
|
||||
tenantByCodeCache.set(tenant.Code, cloneTenant(tenant))
|
||||
return tenant, nil
|
||||
} else if err != nil {
|
||||
logs.Warn.Printf("admin internal tenant by id fallback failed: tenant=%d err=%v", id, err)
|
||||
}
|
||||
}
|
||||
tenantAdp, ok := adp.(adapter.TenantAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
@@ -294,6 +345,29 @@ func (tenantsMapper) GetByID(id types.TenantID) (*types.Tenant, error) {
|
||||
return tenant, err
|
||||
}
|
||||
|
||||
func (tenantsMapper) ListActive(limit int) ([]types.Tenant, error) {
|
||||
if limit <= 0 {
|
||||
limit = 1000
|
||||
}
|
||||
if adminInternalConfigProvider != nil {
|
||||
if tenants, err := adminInternalConfigProvider.ListActiveTenants(limit); err == nil {
|
||||
for i := range tenants {
|
||||
tenant := tenants[i]
|
||||
tenantByIDCache.set(strconv.FormatInt(int64(tenant.ID), 10), cloneTenant(&tenant))
|
||||
tenantByCodeCache.set(tenant.Code, cloneTenant(&tenant))
|
||||
}
|
||||
return tenants, nil
|
||||
} else {
|
||||
logs.Warn.Printf("admin internal active tenants fallback failed: err=%v", err)
|
||||
}
|
||||
}
|
||||
tenantAdp, ok := adp.(adapter.TenantAdapter)
|
||||
if !ok {
|
||||
return nil, types.ErrUnsupported
|
||||
}
|
||||
return tenantAdp.TenantListActive(limit)
|
||||
}
|
||||
|
||||
func tenantAuthAdapter(tenantID types.TenantID) (adapter.TenantAuthAdapter, error) {
|
||||
if !tenantID.IsValid() {
|
||||
return nil, types.ErrMalformed
|
||||
@@ -1267,6 +1341,8 @@ func subscriptionCacheID(topic string, user types.Uid, keepDeleted bool) string
|
||||
// MessagesPersistenceInterface is an interface which defines methods for persistent storage of messages.
|
||||
type MessagesPersistenceInterface interface {
|
||||
Save(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error)
|
||||
PreparePersist(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error)
|
||||
PersistPrepared(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error)
|
||||
GetOne(tenantID types.TenantID, topic string, seq int64) (*types.Message, error)
|
||||
Recall(tenantID types.TenantID, topic string, seq int64, actor types.Uid, expectedVersion int, recalledAt time.Time) (*types.Message, error)
|
||||
Edit(tenantID types.TenantID, topic string, seq int64, actor types.Uid, expectedVersion int, head types.KVMap, content any, reason string, editedAt time.Time) (*types.Message, error)
|
||||
@@ -3063,6 +3139,17 @@ func cachedBlockContains(tenantID types.TenantID, blocker, blocked types.Uid) (b
|
||||
|
||||
// Save message
|
||||
func (messagesMapper) Save(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error) {
|
||||
saveResult, err := Messages.PreparePersist(tenantID, msg, attachmentURLs, readBySender)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if saveResult != nil && saveResult.Duplicate {
|
||||
return saveResult, nil
|
||||
}
|
||||
return Messages.PersistPrepared(tenantID, msg, attachmentURLs, readBySender)
|
||||
}
|
||||
|
||||
func (messagesMapper) PreparePersist(tenantID types.TenantID, msg *types.Message, _ []string, _ bool) (*types.MessageSaveResult, error) {
|
||||
if msg == nil || msg.TenantID != tenantID {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
@@ -3126,12 +3213,29 @@ func (messagesMapper) Save(tenantID types.TenantID, msg *types.Message, attachme
|
||||
}
|
||||
msg.InitTimes()
|
||||
msg.SetUid(Store.GetUid())
|
||||
// Increment topic's or user's SeqId
|
||||
// Reserve topic's or user's SeqId before optional async persistence.
|
||||
err = tenantAdp.TenantTopicUpdateOnMessage(tenantID, msg.Topic, msg)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &types.MessageSaveResult{SeqId: msg.SeqId}, nil
|
||||
}
|
||||
|
||||
func (messagesMapper) PersistPrepared(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error) {
|
||||
if msg == nil || msg.TenantID != tenantID || msg.Topic == "" || msg.SeqId <= 0 {
|
||||
return nil, types.ErrMalformed
|
||||
}
|
||||
tenantAdp, err := tenantBusinessAdapter(tenantID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
clientMsgID, err := normalizeClientMsgID(msg.Head)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
msg.ClientMsgID = clientMsgID
|
||||
fromUid := types.ParseUid(msg.From)
|
||||
isGroupMessage := types.GetTopicCat(msg.Topic) == types.TopicCatGrp
|
||||
if isGroupMessage {
|
||||
err = tenantAdp.TenantGroupMessageSave(tenantID, msg)
|
||||
} else {
|
||||
@@ -3220,6 +3324,14 @@ func (messagesMapper) Save(tenantID types.TenantID, msg *types.Message, attachme
|
||||
return &types.MessageSaveResult{SeqId: msg.SeqId, MarkedReadBySender: markedReadBySender}, nil
|
||||
}
|
||||
|
||||
func PrepareMessagePersist(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error) {
|
||||
return Messages.PreparePersist(tenantID, msg, attachmentURLs, readBySender)
|
||||
}
|
||||
|
||||
func PersistPreparedMessage(tenantID types.TenantID, msg *types.Message, attachmentURLs []string, readBySender bool) (*types.MessageSaveResult, error) {
|
||||
return Messages.PersistPrepared(tenantID, msg, attachmentURLs, readBySender)
|
||||
}
|
||||
|
||||
func retryTenantMessageSaveAfterSeqConflict(tenantAdp adapter.TenantBusinessAdapter, tenantID types.TenantID, msg *types.Message) error {
|
||||
latest, err := tenantAdp.TenantMessageGetAll(tenantID, msg.Topic, types.ZeroUid, &types.QueryOpt{Before: 1 << 62, Limit: 1})
|
||||
if err != nil {
|
||||
@@ -3821,7 +3933,7 @@ func (fileMapper) LinkAttachments(tenantID types.TenantID, topic string, msgId t
|
||||
|
||||
if len(fids) > 0 {
|
||||
userId := types.ZeroUid
|
||||
if types.GetTopicCat(topic) == types.TopicCatMe {
|
||||
if topic != "" && types.GetTopicCat(topic) == types.TopicCatMe {
|
||||
userId = types.ParseUserId(topic)
|
||||
topic = ""
|
||||
}
|
||||
@@ -4353,6 +4465,7 @@ func init() {
|
||||
Tenants = tenantsMapper{}
|
||||
RegistrationConfig = registrationConfigMapper{}
|
||||
TenantEntry = tenantEntryMapper{}
|
||||
InternalAdminQueries = internalAdminQueryMapper{}
|
||||
Users = usersMapper{}
|
||||
Topics = topicsMapper{}
|
||||
Subs = subsMapper{}
|
||||
|
||||
Reference in New Issue
Block a user