fix shared-db tenant runtime gaps
This commit is contained in:
@@ -897,6 +897,78 @@ func tenantTopicCreate(tx *sqlx.Tx, topic *t.Topic) error {
|
||||
return addTenantTags(tx, topic.TenantID, "im_topictags", "topic", topic.Id, topic.Tags, false)
|
||||
}
|
||||
|
||||
// createTenantSubscription mirrors createSubscription but keeps the subscription
|
||||
// bound to the logical tenant in shared-database deployments.
|
||||
func createTenantSubscription(tx *sqlx.Tx, tenantID t.TenantID, sub *t.Subscription, undelete bool) error {
|
||||
if sub == nil || tenantID.IsZero() || sub.TenantID != tenantID {
|
||||
return t.ErrMalformed
|
||||
}
|
||||
isOwner := (sub.ModeGiven & sub.ModeWant).IsOwner()
|
||||
|
||||
jpriv := common.ToJSON(sub.Private)
|
||||
decodedUID := decodeUID(t.ParseUid(sub.User))
|
||||
|
||||
existing := struct {
|
||||
ID int64 `db:"id"`
|
||||
DeletedAt sql.NullTime `db:"deletedat"`
|
||||
}{}
|
||||
err := tx.Get(&existing,
|
||||
"SELECT id,deletedat FROM im_subscriptions WHERE tenant_id=? AND topic=? AND userid=? ORDER BY deletedat IS NULL DESC,id ASC LIMIT 1",
|
||||
tenantID, sub.Topic, decodedUID)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
if err == nil {
|
||||
if existing.DeletedAt.Valid {
|
||||
_, err = tx.Exec("UPDATE im_subscriptions SET createdat=?,updatedat=?,deletedat=NULL,modeWant=?,modeGiven=?,"+
|
||||
"delid=0,recvseqid=0,readseqid=0,private=? WHERE tenant_id=? AND id=?",
|
||||
sub.CreatedAt, sub.UpdatedAt, sub.ModeWant.String(), sub.ModeGiven.String(), jpriv, tenantID, existing.ID)
|
||||
} else {
|
||||
_, err = tx.Exec("UPDATE im_subscriptions SET updatedat=?,modeWant=?,modeGiven=?,private=? WHERE tenant_id=? AND id=?",
|
||||
sub.UpdatedAt, sub.ModeWant.String(), sub.ModeGiven.String(), jpriv, tenantID, existing.ID)
|
||||
}
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if isOwner {
|
||||
_, err = tx.Exec("UPDATE im_topics SET owner=? WHERE tenant_id=? AND name=?", decodedUID, tenantID, sub.Topic)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
subID, err := nextSnowflakeID()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
_, err = tx.Exec(
|
||||
"INSERT INTO im_subscriptions(id,tenant_id,createdat,updatedat,deletedat,userid,topic,modeWant,modeGiven,private) "+
|
||||
"VALUES(?,?,?,?,NULL,?,?,?,?,?)",
|
||||
subID, tenantID, sub.CreatedAt, sub.UpdatedAt, decodedUID, sub.Topic, sub.ModeWant.String(), sub.ModeGiven.String(), jpriv)
|
||||
if isIDOutOfRange(err) {
|
||||
_, err = tx.Exec(
|
||||
"INSERT INTO im_subscriptions(tenant_id,createdat,updatedat,deletedat,userid,topic,modeWant,modeGiven,private) "+
|
||||
"VALUES(?,?,?,NULL,?,?,?,?,?)",
|
||||
tenantID, sub.CreatedAt, sub.UpdatedAt, decodedUID, sub.Topic, sub.ModeWant.String(), sub.ModeGiven.String(), jpriv)
|
||||
}
|
||||
|
||||
if err != nil && isDupe(err) {
|
||||
if undelete {
|
||||
_, err = tx.Exec("UPDATE im_subscriptions SET createdat=?,updatedat=?,deletedat=NULL,modeWant=?,modeGiven=?,"+
|
||||
"delid=0,recvseqid=0,readseqid=0 WHERE tenant_id=? AND topic=? AND userid=?",
|
||||
sub.CreatedAt, sub.UpdatedAt, sub.ModeWant.String(), sub.ModeGiven.String(), tenantID, sub.Topic, decodedUID)
|
||||
} else {
|
||||
_, err = tx.Exec("UPDATE im_subscriptions SET createdat=?,updatedat=?,deletedat=NULL,modeWant=?,modeGiven=?,"+
|
||||
"delid=0,recvseqid=0,readseqid=0,private=? WHERE tenant_id=? AND topic=? AND userid=?",
|
||||
sub.CreatedAt, sub.UpdatedAt, sub.ModeWant.String(), sub.ModeGiven.String(), jpriv, tenantID, sub.Topic, decodedUID)
|
||||
}
|
||||
}
|
||||
|
||||
if err == nil && isOwner {
|
||||
_, err = tx.Exec("UPDATE im_topics SET owner=? WHERE tenant_id=? AND name=?", decodedUID, tenantID, sub.Topic)
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (a *adapter) TenantTopicCreate(id t.TenantID, topic *t.Topic) error {
|
||||
tenantAdp, err := a.routedTenantAdapter(id)
|
||||
if err != nil || topic == nil || topic.TenantID != id {
|
||||
@@ -951,17 +1023,17 @@ func (a *adapter) TenantTopicCreateP2P(id t.TenantID, one, two *t.Subscription)
|
||||
tx.Rollback()
|
||||
}
|
||||
}()
|
||||
if err = createSubscription(tx, one, false); err != nil {
|
||||
if err = createTenantSubscription(tx, id, one, false); err != nil {
|
||||
return err
|
||||
}
|
||||
if err = createSubscription(tx, two, true); err != nil {
|
||||
if err = createTenantSubscription(tx, id, two, true); err != nil {
|
||||
return err
|
||||
}
|
||||
topic := &t.Topic{TenantID: id, ObjHeader: t.ObjHeader{Id: one.Topic}}
|
||||
topic.ObjHeader.MergeTimes(&one.ObjHeader)
|
||||
topic.TouchedAt = one.GetTouchedAt()
|
||||
var existingTopicID int64
|
||||
err = tx.Get(&existingTopicID, "SELECT id FROM im_topics WHERE name=? ORDER BY id ASC LIMIT 1", topic.Id)
|
||||
err = tx.Get(&existingTopicID, "SELECT id FROM im_topics WHERE tenant_id=? AND name=? ORDER BY id ASC LIMIT 1", id, topic.Id)
|
||||
if err != nil && err != sql.ErrNoRows {
|
||||
return err
|
||||
}
|
||||
@@ -969,8 +1041,8 @@ func (a *adapter) TenantTopicCreateP2P(id t.TenantID, one, two *t.Subscription)
|
||||
if err = tenantTopicCreate(tx, topic); err != nil {
|
||||
return err
|
||||
}
|
||||
} else if _, err = tx.ExecContext(ctx, "UPDATE im_topics SET updatedat=?,touchedat=?,state=? WHERE id=?",
|
||||
topic.UpdatedAt, topic.TouchedAt, t.StateOK, existingTopicID); err != nil {
|
||||
} else if _, err = tx.ExecContext(ctx, "UPDATE im_topics SET updatedat=?,touchedat=?,state=? WHERE tenant_id=? AND id=?",
|
||||
topic.UpdatedAt, topic.TouchedAt, t.StateOK, id, existingTopicID); err != nil {
|
||||
return err
|
||||
}
|
||||
return tx.Commit()
|
||||
@@ -1403,7 +1475,7 @@ func (a *adapter) TenantTopicShare(id t.TenantID, topic string, subs []*t.Subscr
|
||||
}
|
||||
}()
|
||||
for _, sub := range subs {
|
||||
if err = createSubscription(tx, sub, true); err != nil {
|
||||
if err = createTenantSubscription(tx, id, sub, true); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user