diff --git a/storage-new/dbgen/failed_outbound_requests.gen.go b/storage-new/dbgen/failed_outbound_requests.gen.go new file mode 100644 index 0000000..45b4405 --- /dev/null +++ b/storage-new/dbgen/failed_outbound_requests.gen.go @@ -0,0 +1,840 @@ +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. +// Code generated by gorm.io/gen. DO NOT EDIT. + +package dbgen + +import ( + "context" + "database/sql" + + "git.mstar.dev/mstar/linstrom/storage-new/models" + "gorm.io/gorm" + "gorm.io/gorm/clause" + "gorm.io/gorm/schema" + + "gorm.io/gen" + "gorm.io/gen/field" + + "gorm.io/plugin/dbresolver" +) + +func newFailedOutboundRequest(db *gorm.DB, opts ...gen.DOOption) failedOutboundRequest { + _failedOutboundRequest := failedOutboundRequest{} + + _failedOutboundRequest.failedOutboundRequestDo.UseDB(db, opts...) + _failedOutboundRequest.failedOutboundRequestDo.UseModel(&models.FailedOutboundRequest{}) + + tableName := _failedOutboundRequest.failedOutboundRequestDo.TableName() + _failedOutboundRequest.ALL = field.NewAsterisk(tableName) + _failedOutboundRequest.Id = field.NewUint64(tableName, "id") + _failedOutboundRequest.RawData = field.NewBytes(tableName, "raw_data") + _failedOutboundRequest.Target = field.NewString(tableName, "target") + _failedOutboundRequest.FirstAttempt = field.NewTime(tableName, "first_attempt") + _failedOutboundRequest.LastAttempt = field.NewTime(tableName, "last_attempt") + _failedOutboundRequest.ActingUserId = field.NewString(tableName, "acting_user_id") + _failedOutboundRequest.NrOfAttempts = field.NewUint32(tableName, "nr_of_attempts") + _failedOutboundRequest.LastFailureReason = field.NewString(tableName, "last_failure_reason") + _failedOutboundRequest.TargetServerId = field.NewUint(tableName, "target_server_id") + _failedOutboundRequest.ActingUser = failedOutboundRequestBelongsToActingUser{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("ActingUser", "models.User"), + Server: struct { + field.RelationField + Icon struct { + field.RelationField + } + Metadata struct { + field.RelationField + RemoteServer struct { + field.RelationField + } + } + }{ + RelationField: field.NewRelation("ActingUser.Server", "models.RemoteServer"), + Icon: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Server.Icon", "models.MediaMetadata"), + }, + Metadata: struct { + field.RelationField + RemoteServer struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.Server.Metadata", "models.RemoteServerMetadata"), + RemoteServer: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Server.Metadata.RemoteServer", "models.RemoteServer"), + }, + }, + }, + Icon: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Icon", "models.MediaMetadata"), + }, + Background: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Background", "models.MediaMetadata"), + }, + Banner: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Banner", "models.MediaMetadata"), + }, + RemoteInfo: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.RemoteInfo", "models.UserRemoteLinks"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.RemoteInfo.User", "models.User"), + }, + }, + InfoFields: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.InfoFields", "models.UserInfoField"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.InfoFields.User", "models.User"), + }, + }, + BeingTypes: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.BeingTypes", "models.UserToBeing"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.BeingTypes.User", "models.User"), + }, + }, + Tags: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.Tags", "models.UserToTag"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Tags.User", "models.User"), + }, + }, + Relations: struct { + field.RelationField + User struct { + field.RelationField + } + TargetUser struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.Relations", "models.UserToUserRelation"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Relations.User", "models.User"), + }, + TargetUser: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Relations.TargetUser", "models.User"), + }, + }, + Pronouns: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.Pronouns", "models.UserToPronoun"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Pronouns.User", "models.User"), + }, + }, + Roles: struct { + field.RelationField + User struct { + field.RelationField + } + Role struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.Roles", "models.UserToRole"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Roles.User", "models.User"), + }, + Role: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.Roles.Role", "models.Role"), + }, + }, + AuthMethods: struct { + field.RelationField + User struct { + field.RelationField + } + }{ + RelationField: field.NewRelation("ActingUser.AuthMethods", "models.UserAuthMethod"), + User: struct { + field.RelationField + }{ + RelationField: field.NewRelation("ActingUser.AuthMethods.User", "models.User"), + }, + }, + } + + _failedOutboundRequest.TargetServer = failedOutboundRequestBelongsToTargetServer{ + db: db.Session(&gorm.Session{}), + + RelationField: field.NewRelation("TargetServer", "models.RemoteServer"), + } + + _failedOutboundRequest.fillFieldMap() + + return _failedOutboundRequest +} + +type failedOutboundRequest struct { + failedOutboundRequestDo + + ALL field.Asterisk + Id field.Uint64 + RawData field.Bytes + Target field.String + FirstAttempt field.Time + LastAttempt field.Time + ActingUserId field.String + NrOfAttempts field.Uint32 + LastFailureReason field.String + TargetServerId field.Uint + ActingUser failedOutboundRequestBelongsToActingUser + + TargetServer failedOutboundRequestBelongsToTargetServer + + fieldMap map[string]field.Expr +} + +func (f failedOutboundRequest) Table(newTableName string) *failedOutboundRequest { + f.failedOutboundRequestDo.UseTable(newTableName) + return f.updateTableName(newTableName) +} + +func (f failedOutboundRequest) As(alias string) *failedOutboundRequest { + f.failedOutboundRequestDo.DO = *(f.failedOutboundRequestDo.As(alias).(*gen.DO)) + return f.updateTableName(alias) +} + +func (f *failedOutboundRequest) updateTableName(table string) *failedOutboundRequest { + f.ALL = field.NewAsterisk(table) + f.Id = field.NewUint64(table, "id") + f.RawData = field.NewBytes(table, "raw_data") + f.Target = field.NewString(table, "target") + f.FirstAttempt = field.NewTime(table, "first_attempt") + f.LastAttempt = field.NewTime(table, "last_attempt") + f.ActingUserId = field.NewString(table, "acting_user_id") + f.NrOfAttempts = field.NewUint32(table, "nr_of_attempts") + f.LastFailureReason = field.NewString(table, "last_failure_reason") + f.TargetServerId = field.NewUint(table, "target_server_id") + + f.fillFieldMap() + + return f +} + +func (f *failedOutboundRequest) GetFieldByName(fieldName string) (field.OrderExpr, bool) { + _f, ok := f.fieldMap[fieldName] + if !ok || _f == nil { + return nil, false + } + _oe, ok := _f.(field.OrderExpr) + return _oe, ok +} + +func (f *failedOutboundRequest) fillFieldMap() { + f.fieldMap = make(map[string]field.Expr, 11) + f.fieldMap["id"] = f.Id + f.fieldMap["raw_data"] = f.RawData + f.fieldMap["target"] = f.Target + f.fieldMap["first_attempt"] = f.FirstAttempt + f.fieldMap["last_attempt"] = f.LastAttempt + f.fieldMap["acting_user_id"] = f.ActingUserId + f.fieldMap["nr_of_attempts"] = f.NrOfAttempts + f.fieldMap["last_failure_reason"] = f.LastFailureReason + f.fieldMap["target_server_id"] = f.TargetServerId + +} + +func (f failedOutboundRequest) clone(db *gorm.DB) failedOutboundRequest { + f.failedOutboundRequestDo.ReplaceConnPool(db.Statement.ConnPool) + f.ActingUser.db = db.Session(&gorm.Session{Initialized: true}) + f.ActingUser.db.Statement.ConnPool = db.Statement.ConnPool + f.TargetServer.db = db.Session(&gorm.Session{Initialized: true}) + f.TargetServer.db.Statement.ConnPool = db.Statement.ConnPool + return f +} + +func (f failedOutboundRequest) replaceDB(db *gorm.DB) failedOutboundRequest { + f.failedOutboundRequestDo.ReplaceDB(db) + f.ActingUser.db = db.Session(&gorm.Session{}) + f.TargetServer.db = db.Session(&gorm.Session{}) + return f +} + +type failedOutboundRequestBelongsToActingUser struct { + db *gorm.DB + + field.RelationField + + Server struct { + field.RelationField + Icon struct { + field.RelationField + } + Metadata struct { + field.RelationField + RemoteServer struct { + field.RelationField + } + } + } + Icon struct { + field.RelationField + } + Background struct { + field.RelationField + } + Banner struct { + field.RelationField + } + RemoteInfo struct { + field.RelationField + User struct { + field.RelationField + } + } + InfoFields struct { + field.RelationField + User struct { + field.RelationField + } + } + BeingTypes struct { + field.RelationField + User struct { + field.RelationField + } + } + Tags struct { + field.RelationField + User struct { + field.RelationField + } + } + Relations struct { + field.RelationField + User struct { + field.RelationField + } + TargetUser struct { + field.RelationField + } + } + Pronouns struct { + field.RelationField + User struct { + field.RelationField + } + } + Roles struct { + field.RelationField + User struct { + field.RelationField + } + Role struct { + field.RelationField + } + } + AuthMethods struct { + field.RelationField + User struct { + field.RelationField + } + } +} + +func (a failedOutboundRequestBelongsToActingUser) Where(conds ...field.Expr) *failedOutboundRequestBelongsToActingUser { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a failedOutboundRequestBelongsToActingUser) WithContext(ctx context.Context) *failedOutboundRequestBelongsToActingUser { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a failedOutboundRequestBelongsToActingUser) Session(session *gorm.Session) *failedOutboundRequestBelongsToActingUser { + a.db = a.db.Session(session) + return &a +} + +func (a failedOutboundRequestBelongsToActingUser) Model(m *models.FailedOutboundRequest) *failedOutboundRequestBelongsToActingUserTx { + return &failedOutboundRequestBelongsToActingUserTx{a.db.Model(m).Association(a.Name())} +} + +func (a failedOutboundRequestBelongsToActingUser) Unscoped() *failedOutboundRequestBelongsToActingUser { + a.db = a.db.Unscoped() + return &a +} + +type failedOutboundRequestBelongsToActingUserTx struct{ tx *gorm.Association } + +func (a failedOutboundRequestBelongsToActingUserTx) Find() (result *models.User, err error) { + return result, a.tx.Find(&result) +} + +func (a failedOutboundRequestBelongsToActingUserTx) Append(values ...*models.User) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a failedOutboundRequestBelongsToActingUserTx) Replace(values ...*models.User) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a failedOutboundRequestBelongsToActingUserTx) Delete(values ...*models.User) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a failedOutboundRequestBelongsToActingUserTx) Clear() error { + return a.tx.Clear() +} + +func (a failedOutboundRequestBelongsToActingUserTx) Count() int64 { + return a.tx.Count() +} + +func (a failedOutboundRequestBelongsToActingUserTx) Unscoped() *failedOutboundRequestBelongsToActingUserTx { + a.tx = a.tx.Unscoped() + return &a +} + +type failedOutboundRequestBelongsToTargetServer struct { + db *gorm.DB + + field.RelationField +} + +func (a failedOutboundRequestBelongsToTargetServer) Where(conds ...field.Expr) *failedOutboundRequestBelongsToTargetServer { + if len(conds) == 0 { + return &a + } + + exprs := make([]clause.Expression, 0, len(conds)) + for _, cond := range conds { + exprs = append(exprs, cond.BeCond().(clause.Expression)) + } + a.db = a.db.Clauses(clause.Where{Exprs: exprs}) + return &a +} + +func (a failedOutboundRequestBelongsToTargetServer) WithContext(ctx context.Context) *failedOutboundRequestBelongsToTargetServer { + a.db = a.db.WithContext(ctx) + return &a +} + +func (a failedOutboundRequestBelongsToTargetServer) Session(session *gorm.Session) *failedOutboundRequestBelongsToTargetServer { + a.db = a.db.Session(session) + return &a +} + +func (a failedOutboundRequestBelongsToTargetServer) Model(m *models.FailedOutboundRequest) *failedOutboundRequestBelongsToTargetServerTx { + return &failedOutboundRequestBelongsToTargetServerTx{a.db.Model(m).Association(a.Name())} +} + +func (a failedOutboundRequestBelongsToTargetServer) Unscoped() *failedOutboundRequestBelongsToTargetServer { + a.db = a.db.Unscoped() + return &a +} + +type failedOutboundRequestBelongsToTargetServerTx struct{ tx *gorm.Association } + +func (a failedOutboundRequestBelongsToTargetServerTx) Find() (result *models.RemoteServer, err error) { + return result, a.tx.Find(&result) +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Append(values ...*models.RemoteServer) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Append(targetValues...) +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Replace(values ...*models.RemoteServer) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Replace(targetValues...) +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Delete(values ...*models.RemoteServer) (err error) { + targetValues := make([]interface{}, len(values)) + for i, v := range values { + targetValues[i] = v + } + return a.tx.Delete(targetValues...) +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Clear() error { + return a.tx.Clear() +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Count() int64 { + return a.tx.Count() +} + +func (a failedOutboundRequestBelongsToTargetServerTx) Unscoped() *failedOutboundRequestBelongsToTargetServerTx { + a.tx = a.tx.Unscoped() + return &a +} + +type failedOutboundRequestDo struct{ gen.DO } + +type IFailedOutboundRequestDo interface { + gen.SubQuery + Debug() IFailedOutboundRequestDo + WithContext(ctx context.Context) IFailedOutboundRequestDo + WithResult(fc func(tx gen.Dao)) gen.ResultInfo + ReplaceDB(db *gorm.DB) + ReadDB() IFailedOutboundRequestDo + WriteDB() IFailedOutboundRequestDo + As(alias string) gen.Dao + Session(config *gorm.Session) IFailedOutboundRequestDo + Columns(cols ...field.Expr) gen.Columns + Clauses(conds ...clause.Expression) IFailedOutboundRequestDo + Not(conds ...gen.Condition) IFailedOutboundRequestDo + Or(conds ...gen.Condition) IFailedOutboundRequestDo + Select(conds ...field.Expr) IFailedOutboundRequestDo + Where(conds ...gen.Condition) IFailedOutboundRequestDo + Order(conds ...field.Expr) IFailedOutboundRequestDo + Distinct(cols ...field.Expr) IFailedOutboundRequestDo + Omit(cols ...field.Expr) IFailedOutboundRequestDo + Join(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo + LeftJoin(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo + RightJoin(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo + Group(cols ...field.Expr) IFailedOutboundRequestDo + Having(conds ...gen.Condition) IFailedOutboundRequestDo + Limit(limit int) IFailedOutboundRequestDo + Offset(offset int) IFailedOutboundRequestDo + Count() (count int64, err error) + Scopes(funcs ...func(gen.Dao) gen.Dao) IFailedOutboundRequestDo + Unscoped() IFailedOutboundRequestDo + Create(values ...*models.FailedOutboundRequest) error + CreateInBatches(values []*models.FailedOutboundRequest, batchSize int) error + Save(values ...*models.FailedOutboundRequest) error + First() (*models.FailedOutboundRequest, error) + Take() (*models.FailedOutboundRequest, error) + Last() (*models.FailedOutboundRequest, error) + Find() ([]*models.FailedOutboundRequest, error) + FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.FailedOutboundRequest, err error) + FindInBatches(result *[]*models.FailedOutboundRequest, batchSize int, fc func(tx gen.Dao, batch int) error) error + Pluck(column field.Expr, dest interface{}) error + Delete(...*models.FailedOutboundRequest) (info gen.ResultInfo, err error) + Update(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + Updates(value interface{}) (info gen.ResultInfo, err error) + UpdateColumn(column field.Expr, value interface{}) (info gen.ResultInfo, err error) + UpdateColumnSimple(columns ...field.AssignExpr) (info gen.ResultInfo, err error) + UpdateColumns(value interface{}) (info gen.ResultInfo, err error) + UpdateFrom(q gen.SubQuery) gen.Dao + Attrs(attrs ...field.AssignExpr) IFailedOutboundRequestDo + Assign(attrs ...field.AssignExpr) IFailedOutboundRequestDo + Joins(fields ...field.RelationField) IFailedOutboundRequestDo + Preload(fields ...field.RelationField) IFailedOutboundRequestDo + FirstOrInit() (*models.FailedOutboundRequest, error) + FirstOrCreate() (*models.FailedOutboundRequest, error) + FindByPage(offset int, limit int) (result []*models.FailedOutboundRequest, count int64, err error) + ScanByPage(result interface{}, offset int, limit int) (count int64, err error) + Rows() (*sql.Rows, error) + Row() *sql.Row + Scan(result interface{}) (err error) + Returning(value interface{}, columns ...string) IFailedOutboundRequestDo + UnderlyingDB() *gorm.DB + schema.Tabler +} + +func (f failedOutboundRequestDo) Debug() IFailedOutboundRequestDo { + return f.withDO(f.DO.Debug()) +} + +func (f failedOutboundRequestDo) WithContext(ctx context.Context) IFailedOutboundRequestDo { + return f.withDO(f.DO.WithContext(ctx)) +} + +func (f failedOutboundRequestDo) ReadDB() IFailedOutboundRequestDo { + return f.Clauses(dbresolver.Read) +} + +func (f failedOutboundRequestDo) WriteDB() IFailedOutboundRequestDo { + return f.Clauses(dbresolver.Write) +} + +func (f failedOutboundRequestDo) Session(config *gorm.Session) IFailedOutboundRequestDo { + return f.withDO(f.DO.Session(config)) +} + +func (f failedOutboundRequestDo) Clauses(conds ...clause.Expression) IFailedOutboundRequestDo { + return f.withDO(f.DO.Clauses(conds...)) +} + +func (f failedOutboundRequestDo) Returning(value interface{}, columns ...string) IFailedOutboundRequestDo { + return f.withDO(f.DO.Returning(value, columns...)) +} + +func (f failedOutboundRequestDo) Not(conds ...gen.Condition) IFailedOutboundRequestDo { + return f.withDO(f.DO.Not(conds...)) +} + +func (f failedOutboundRequestDo) Or(conds ...gen.Condition) IFailedOutboundRequestDo { + return f.withDO(f.DO.Or(conds...)) +} + +func (f failedOutboundRequestDo) Select(conds ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Select(conds...)) +} + +func (f failedOutboundRequestDo) Where(conds ...gen.Condition) IFailedOutboundRequestDo { + return f.withDO(f.DO.Where(conds...)) +} + +func (f failedOutboundRequestDo) Order(conds ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Order(conds...)) +} + +func (f failedOutboundRequestDo) Distinct(cols ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Distinct(cols...)) +} + +func (f failedOutboundRequestDo) Omit(cols ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Omit(cols...)) +} + +func (f failedOutboundRequestDo) Join(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Join(table, on...)) +} + +func (f failedOutboundRequestDo) LeftJoin(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.LeftJoin(table, on...)) +} + +func (f failedOutboundRequestDo) RightJoin(table schema.Tabler, on ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.RightJoin(table, on...)) +} + +func (f failedOutboundRequestDo) Group(cols ...field.Expr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Group(cols...)) +} + +func (f failedOutboundRequestDo) Having(conds ...gen.Condition) IFailedOutboundRequestDo { + return f.withDO(f.DO.Having(conds...)) +} + +func (f failedOutboundRequestDo) Limit(limit int) IFailedOutboundRequestDo { + return f.withDO(f.DO.Limit(limit)) +} + +func (f failedOutboundRequestDo) Offset(offset int) IFailedOutboundRequestDo { + return f.withDO(f.DO.Offset(offset)) +} + +func (f failedOutboundRequestDo) Scopes(funcs ...func(gen.Dao) gen.Dao) IFailedOutboundRequestDo { + return f.withDO(f.DO.Scopes(funcs...)) +} + +func (f failedOutboundRequestDo) Unscoped() IFailedOutboundRequestDo { + return f.withDO(f.DO.Unscoped()) +} + +func (f failedOutboundRequestDo) Create(values ...*models.FailedOutboundRequest) error { + if len(values) == 0 { + return nil + } + return f.DO.Create(values) +} + +func (f failedOutboundRequestDo) CreateInBatches(values []*models.FailedOutboundRequest, batchSize int) error { + return f.DO.CreateInBatches(values, batchSize) +} + +// Save : !!! underlying implementation is different with GORM +// The method is equivalent to executing the statement: db.Clauses(clause.OnConflict{UpdateAll: true}).Create(values) +func (f failedOutboundRequestDo) Save(values ...*models.FailedOutboundRequest) error { + if len(values) == 0 { + return nil + } + return f.DO.Save(values) +} + +func (f failedOutboundRequestDo) First() (*models.FailedOutboundRequest, error) { + if result, err := f.DO.First(); err != nil { + return nil, err + } else { + return result.(*models.FailedOutboundRequest), nil + } +} + +func (f failedOutboundRequestDo) Take() (*models.FailedOutboundRequest, error) { + if result, err := f.DO.Take(); err != nil { + return nil, err + } else { + return result.(*models.FailedOutboundRequest), nil + } +} + +func (f failedOutboundRequestDo) Last() (*models.FailedOutboundRequest, error) { + if result, err := f.DO.Last(); err != nil { + return nil, err + } else { + return result.(*models.FailedOutboundRequest), nil + } +} + +func (f failedOutboundRequestDo) Find() ([]*models.FailedOutboundRequest, error) { + result, err := f.DO.Find() + return result.([]*models.FailedOutboundRequest), err +} + +func (f failedOutboundRequestDo) FindInBatch(batchSize int, fc func(tx gen.Dao, batch int) error) (results []*models.FailedOutboundRequest, err error) { + buf := make([]*models.FailedOutboundRequest, 0, batchSize) + err = f.DO.FindInBatches(&buf, batchSize, func(tx gen.Dao, batch int) error { + defer func() { results = append(results, buf...) }() + return fc(tx, batch) + }) + return results, err +} + +func (f failedOutboundRequestDo) FindInBatches(result *[]*models.FailedOutboundRequest, batchSize int, fc func(tx gen.Dao, batch int) error) error { + return f.DO.FindInBatches(result, batchSize, fc) +} + +func (f failedOutboundRequestDo) Attrs(attrs ...field.AssignExpr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Attrs(attrs...)) +} + +func (f failedOutboundRequestDo) Assign(attrs ...field.AssignExpr) IFailedOutboundRequestDo { + return f.withDO(f.DO.Assign(attrs...)) +} + +func (f failedOutboundRequestDo) Joins(fields ...field.RelationField) IFailedOutboundRequestDo { + for _, _f := range fields { + f = *f.withDO(f.DO.Joins(_f)) + } + return &f +} + +func (f failedOutboundRequestDo) Preload(fields ...field.RelationField) IFailedOutboundRequestDo { + for _, _f := range fields { + f = *f.withDO(f.DO.Preload(_f)) + } + return &f +} + +func (f failedOutboundRequestDo) FirstOrInit() (*models.FailedOutboundRequest, error) { + if result, err := f.DO.FirstOrInit(); err != nil { + return nil, err + } else { + return result.(*models.FailedOutboundRequest), nil + } +} + +func (f failedOutboundRequestDo) FirstOrCreate() (*models.FailedOutboundRequest, error) { + if result, err := f.DO.FirstOrCreate(); err != nil { + return nil, err + } else { + return result.(*models.FailedOutboundRequest), nil + } +} + +func (f failedOutboundRequestDo) FindByPage(offset int, limit int) (result []*models.FailedOutboundRequest, count int64, err error) { + result, err = f.Offset(offset).Limit(limit).Find() + if err != nil { + return + } + + if size := len(result); 0 < limit && 0 < size && size < limit { + count = int64(size + offset) + return + } + + count, err = f.Offset(-1).Limit(-1).Count() + return +} + +func (f failedOutboundRequestDo) ScanByPage(result interface{}, offset int, limit int) (count int64, err error) { + count, err = f.Count() + if err != nil { + return + } + + err = f.Offset(offset).Limit(limit).Scan(result) + return +} + +func (f failedOutboundRequestDo) Scan(result interface{}) (err error) { + return f.DO.Scan(result) +} + +func (f failedOutboundRequestDo) Delete(models ...*models.FailedOutboundRequest) (result gen.ResultInfo, err error) { + return f.DO.Delete(models) +} + +func (f *failedOutboundRequestDo) withDO(do gen.Dao) *failedOutboundRequestDo { + f.DO = *do.(*gen.DO) + return f +} diff --git a/storage-new/dbgen/gen.go b/storage-new/dbgen/gen.go index 4994dfc..9b00402 100644 --- a/storage-new/dbgen/gen.go +++ b/storage-new/dbgen/gen.go @@ -16,38 +16,39 @@ import ( ) var ( - Q = new(Query) - AccessToken *accessToken - Activity *activity - Collection *collection - Emote *emote - Feed *feed - LoginProcessToken *loginProcessToken - MediaMetadata *mediaMetadata - Note *note - NoteEdit *noteEdit - NoteTag *noteTag - NoteToAttachment *noteToAttachment - NoteToBoost *noteToBoost - NoteToEmote *noteToEmote - NoteToFeed *noteToFeed - NoteToPing *noteToPing - Notification *notification - Reaction *reaction - RemoteServer *remoteServer - RemoteServerMetadata *remoteServerMetadata - Role *role - ServerMetadata *serverMetadata - UnhandledMessage *unhandledMessage - User *user - UserAuthMethod *userAuthMethod - UserInfoField *userInfoField - UserRemoteLinks *userRemoteLinks - UserToBeing *userToBeing - UserToPronoun *userToPronoun - UserToRole *userToRole - UserToTag *userToTag - UserToUserRelation *userToUserRelation + Q = new(Query) + AccessToken *accessToken + Activity *activity + Collection *collection + Emote *emote + FailedOutboundRequest *failedOutboundRequest + Feed *feed + LoginProcessToken *loginProcessToken + MediaMetadata *mediaMetadata + Note *note + NoteEdit *noteEdit + NoteTag *noteTag + NoteToAttachment *noteToAttachment + NoteToBoost *noteToBoost + NoteToEmote *noteToEmote + NoteToFeed *noteToFeed + NoteToPing *noteToPing + Notification *notification + Reaction *reaction + RemoteServer *remoteServer + RemoteServerMetadata *remoteServerMetadata + Role *role + ServerMetadata *serverMetadata + UnhandledMessage *unhandledMessage + User *user + UserAuthMethod *userAuthMethod + UserInfoField *userInfoField + UserRemoteLinks *userRemoteLinks + UserToBeing *userToBeing + UserToPronoun *userToPronoun + UserToRole *userToRole + UserToTag *userToTag + UserToUserRelation *userToUserRelation ) func SetDefault(db *gorm.DB, opts ...gen.DOOption) { @@ -56,6 +57,7 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { Activity = &Q.Activity Collection = &Q.Collection Emote = &Q.Emote + FailedOutboundRequest = &Q.FailedOutboundRequest Feed = &Q.Feed LoginProcessToken = &Q.LoginProcessToken MediaMetadata = &Q.MediaMetadata @@ -87,113 +89,116 @@ func SetDefault(db *gorm.DB, opts ...gen.DOOption) { func Use(db *gorm.DB, opts ...gen.DOOption) *Query { return &Query{ - db: db, - AccessToken: newAccessToken(db, opts...), - Activity: newActivity(db, opts...), - Collection: newCollection(db, opts...), - Emote: newEmote(db, opts...), - Feed: newFeed(db, opts...), - LoginProcessToken: newLoginProcessToken(db, opts...), - MediaMetadata: newMediaMetadata(db, opts...), - Note: newNote(db, opts...), - NoteEdit: newNoteEdit(db, opts...), - NoteTag: newNoteTag(db, opts...), - NoteToAttachment: newNoteToAttachment(db, opts...), - NoteToBoost: newNoteToBoost(db, opts...), - NoteToEmote: newNoteToEmote(db, opts...), - NoteToFeed: newNoteToFeed(db, opts...), - NoteToPing: newNoteToPing(db, opts...), - Notification: newNotification(db, opts...), - Reaction: newReaction(db, opts...), - RemoteServer: newRemoteServer(db, opts...), - RemoteServerMetadata: newRemoteServerMetadata(db, opts...), - Role: newRole(db, opts...), - ServerMetadata: newServerMetadata(db, opts...), - UnhandledMessage: newUnhandledMessage(db, opts...), - User: newUser(db, opts...), - UserAuthMethod: newUserAuthMethod(db, opts...), - UserInfoField: newUserInfoField(db, opts...), - UserRemoteLinks: newUserRemoteLinks(db, opts...), - UserToBeing: newUserToBeing(db, opts...), - UserToPronoun: newUserToPronoun(db, opts...), - UserToRole: newUserToRole(db, opts...), - UserToTag: newUserToTag(db, opts...), - UserToUserRelation: newUserToUserRelation(db, opts...), + db: db, + AccessToken: newAccessToken(db, opts...), + Activity: newActivity(db, opts...), + Collection: newCollection(db, opts...), + Emote: newEmote(db, opts...), + FailedOutboundRequest: newFailedOutboundRequest(db, opts...), + Feed: newFeed(db, opts...), + LoginProcessToken: newLoginProcessToken(db, opts...), + MediaMetadata: newMediaMetadata(db, opts...), + Note: newNote(db, opts...), + NoteEdit: newNoteEdit(db, opts...), + NoteTag: newNoteTag(db, opts...), + NoteToAttachment: newNoteToAttachment(db, opts...), + NoteToBoost: newNoteToBoost(db, opts...), + NoteToEmote: newNoteToEmote(db, opts...), + NoteToFeed: newNoteToFeed(db, opts...), + NoteToPing: newNoteToPing(db, opts...), + Notification: newNotification(db, opts...), + Reaction: newReaction(db, opts...), + RemoteServer: newRemoteServer(db, opts...), + RemoteServerMetadata: newRemoteServerMetadata(db, opts...), + Role: newRole(db, opts...), + ServerMetadata: newServerMetadata(db, opts...), + UnhandledMessage: newUnhandledMessage(db, opts...), + User: newUser(db, opts...), + UserAuthMethod: newUserAuthMethod(db, opts...), + UserInfoField: newUserInfoField(db, opts...), + UserRemoteLinks: newUserRemoteLinks(db, opts...), + UserToBeing: newUserToBeing(db, opts...), + UserToPronoun: newUserToPronoun(db, opts...), + UserToRole: newUserToRole(db, opts...), + UserToTag: newUserToTag(db, opts...), + UserToUserRelation: newUserToUserRelation(db, opts...), } } type Query struct { db *gorm.DB - AccessToken accessToken - Activity activity - Collection collection - Emote emote - Feed feed - LoginProcessToken loginProcessToken - MediaMetadata mediaMetadata - Note note - NoteEdit noteEdit - NoteTag noteTag - NoteToAttachment noteToAttachment - NoteToBoost noteToBoost - NoteToEmote noteToEmote - NoteToFeed noteToFeed - NoteToPing noteToPing - Notification notification - Reaction reaction - RemoteServer remoteServer - RemoteServerMetadata remoteServerMetadata - Role role - ServerMetadata serverMetadata - UnhandledMessage unhandledMessage - User user - UserAuthMethod userAuthMethod - UserInfoField userInfoField - UserRemoteLinks userRemoteLinks - UserToBeing userToBeing - UserToPronoun userToPronoun - UserToRole userToRole - UserToTag userToTag - UserToUserRelation userToUserRelation + AccessToken accessToken + Activity activity + Collection collection + Emote emote + FailedOutboundRequest failedOutboundRequest + Feed feed + LoginProcessToken loginProcessToken + MediaMetadata mediaMetadata + Note note + NoteEdit noteEdit + NoteTag noteTag + NoteToAttachment noteToAttachment + NoteToBoost noteToBoost + NoteToEmote noteToEmote + NoteToFeed noteToFeed + NoteToPing noteToPing + Notification notification + Reaction reaction + RemoteServer remoteServer + RemoteServerMetadata remoteServerMetadata + Role role + ServerMetadata serverMetadata + UnhandledMessage unhandledMessage + User user + UserAuthMethod userAuthMethod + UserInfoField userInfoField + UserRemoteLinks userRemoteLinks + UserToBeing userToBeing + UserToPronoun userToPronoun + UserToRole userToRole + UserToTag userToTag + UserToUserRelation userToUserRelation } func (q *Query) Available() bool { return q.db != nil } func (q *Query) clone(db *gorm.DB) *Query { return &Query{ - db: db, - AccessToken: q.AccessToken.clone(db), - Activity: q.Activity.clone(db), - Collection: q.Collection.clone(db), - Emote: q.Emote.clone(db), - Feed: q.Feed.clone(db), - LoginProcessToken: q.LoginProcessToken.clone(db), - MediaMetadata: q.MediaMetadata.clone(db), - Note: q.Note.clone(db), - NoteEdit: q.NoteEdit.clone(db), - NoteTag: q.NoteTag.clone(db), - NoteToAttachment: q.NoteToAttachment.clone(db), - NoteToBoost: q.NoteToBoost.clone(db), - NoteToEmote: q.NoteToEmote.clone(db), - NoteToFeed: q.NoteToFeed.clone(db), - NoteToPing: q.NoteToPing.clone(db), - Notification: q.Notification.clone(db), - Reaction: q.Reaction.clone(db), - RemoteServer: q.RemoteServer.clone(db), - RemoteServerMetadata: q.RemoteServerMetadata.clone(db), - Role: q.Role.clone(db), - ServerMetadata: q.ServerMetadata.clone(db), - UnhandledMessage: q.UnhandledMessage.clone(db), - User: q.User.clone(db), - UserAuthMethod: q.UserAuthMethod.clone(db), - UserInfoField: q.UserInfoField.clone(db), - UserRemoteLinks: q.UserRemoteLinks.clone(db), - UserToBeing: q.UserToBeing.clone(db), - UserToPronoun: q.UserToPronoun.clone(db), - UserToRole: q.UserToRole.clone(db), - UserToTag: q.UserToTag.clone(db), - UserToUserRelation: q.UserToUserRelation.clone(db), + db: db, + AccessToken: q.AccessToken.clone(db), + Activity: q.Activity.clone(db), + Collection: q.Collection.clone(db), + Emote: q.Emote.clone(db), + FailedOutboundRequest: q.FailedOutboundRequest.clone(db), + Feed: q.Feed.clone(db), + LoginProcessToken: q.LoginProcessToken.clone(db), + MediaMetadata: q.MediaMetadata.clone(db), + Note: q.Note.clone(db), + NoteEdit: q.NoteEdit.clone(db), + NoteTag: q.NoteTag.clone(db), + NoteToAttachment: q.NoteToAttachment.clone(db), + NoteToBoost: q.NoteToBoost.clone(db), + NoteToEmote: q.NoteToEmote.clone(db), + NoteToFeed: q.NoteToFeed.clone(db), + NoteToPing: q.NoteToPing.clone(db), + Notification: q.Notification.clone(db), + Reaction: q.Reaction.clone(db), + RemoteServer: q.RemoteServer.clone(db), + RemoteServerMetadata: q.RemoteServerMetadata.clone(db), + Role: q.Role.clone(db), + ServerMetadata: q.ServerMetadata.clone(db), + UnhandledMessage: q.UnhandledMessage.clone(db), + User: q.User.clone(db), + UserAuthMethod: q.UserAuthMethod.clone(db), + UserInfoField: q.UserInfoField.clone(db), + UserRemoteLinks: q.UserRemoteLinks.clone(db), + UserToBeing: q.UserToBeing.clone(db), + UserToPronoun: q.UserToPronoun.clone(db), + UserToRole: q.UserToRole.clone(db), + UserToTag: q.UserToTag.clone(db), + UserToUserRelation: q.UserToUserRelation.clone(db), } } @@ -207,108 +212,111 @@ func (q *Query) WriteDB() *Query { func (q *Query) ReplaceDB(db *gorm.DB) *Query { return &Query{ - db: db, - AccessToken: q.AccessToken.replaceDB(db), - Activity: q.Activity.replaceDB(db), - Collection: q.Collection.replaceDB(db), - Emote: q.Emote.replaceDB(db), - Feed: q.Feed.replaceDB(db), - LoginProcessToken: q.LoginProcessToken.replaceDB(db), - MediaMetadata: q.MediaMetadata.replaceDB(db), - Note: q.Note.replaceDB(db), - NoteEdit: q.NoteEdit.replaceDB(db), - NoteTag: q.NoteTag.replaceDB(db), - NoteToAttachment: q.NoteToAttachment.replaceDB(db), - NoteToBoost: q.NoteToBoost.replaceDB(db), - NoteToEmote: q.NoteToEmote.replaceDB(db), - NoteToFeed: q.NoteToFeed.replaceDB(db), - NoteToPing: q.NoteToPing.replaceDB(db), - Notification: q.Notification.replaceDB(db), - Reaction: q.Reaction.replaceDB(db), - RemoteServer: q.RemoteServer.replaceDB(db), - RemoteServerMetadata: q.RemoteServerMetadata.replaceDB(db), - Role: q.Role.replaceDB(db), - ServerMetadata: q.ServerMetadata.replaceDB(db), - UnhandledMessage: q.UnhandledMessage.replaceDB(db), - User: q.User.replaceDB(db), - UserAuthMethod: q.UserAuthMethod.replaceDB(db), - UserInfoField: q.UserInfoField.replaceDB(db), - UserRemoteLinks: q.UserRemoteLinks.replaceDB(db), - UserToBeing: q.UserToBeing.replaceDB(db), - UserToPronoun: q.UserToPronoun.replaceDB(db), - UserToRole: q.UserToRole.replaceDB(db), - UserToTag: q.UserToTag.replaceDB(db), - UserToUserRelation: q.UserToUserRelation.replaceDB(db), + db: db, + AccessToken: q.AccessToken.replaceDB(db), + Activity: q.Activity.replaceDB(db), + Collection: q.Collection.replaceDB(db), + Emote: q.Emote.replaceDB(db), + FailedOutboundRequest: q.FailedOutboundRequest.replaceDB(db), + Feed: q.Feed.replaceDB(db), + LoginProcessToken: q.LoginProcessToken.replaceDB(db), + MediaMetadata: q.MediaMetadata.replaceDB(db), + Note: q.Note.replaceDB(db), + NoteEdit: q.NoteEdit.replaceDB(db), + NoteTag: q.NoteTag.replaceDB(db), + NoteToAttachment: q.NoteToAttachment.replaceDB(db), + NoteToBoost: q.NoteToBoost.replaceDB(db), + NoteToEmote: q.NoteToEmote.replaceDB(db), + NoteToFeed: q.NoteToFeed.replaceDB(db), + NoteToPing: q.NoteToPing.replaceDB(db), + Notification: q.Notification.replaceDB(db), + Reaction: q.Reaction.replaceDB(db), + RemoteServer: q.RemoteServer.replaceDB(db), + RemoteServerMetadata: q.RemoteServerMetadata.replaceDB(db), + Role: q.Role.replaceDB(db), + ServerMetadata: q.ServerMetadata.replaceDB(db), + UnhandledMessage: q.UnhandledMessage.replaceDB(db), + User: q.User.replaceDB(db), + UserAuthMethod: q.UserAuthMethod.replaceDB(db), + UserInfoField: q.UserInfoField.replaceDB(db), + UserRemoteLinks: q.UserRemoteLinks.replaceDB(db), + UserToBeing: q.UserToBeing.replaceDB(db), + UserToPronoun: q.UserToPronoun.replaceDB(db), + UserToRole: q.UserToRole.replaceDB(db), + UserToTag: q.UserToTag.replaceDB(db), + UserToUserRelation: q.UserToUserRelation.replaceDB(db), } } type queryCtx struct { - AccessToken IAccessTokenDo - Activity IActivityDo - Collection ICollectionDo - Emote IEmoteDo - Feed IFeedDo - LoginProcessToken ILoginProcessTokenDo - MediaMetadata IMediaMetadataDo - Note INoteDo - NoteEdit INoteEditDo - NoteTag INoteTagDo - NoteToAttachment INoteToAttachmentDo - NoteToBoost INoteToBoostDo - NoteToEmote INoteToEmoteDo - NoteToFeed INoteToFeedDo - NoteToPing INoteToPingDo - Notification INotificationDo - Reaction IReactionDo - RemoteServer IRemoteServerDo - RemoteServerMetadata IRemoteServerMetadataDo - Role IRoleDo - ServerMetadata IServerMetadataDo - UnhandledMessage IUnhandledMessageDo - User IUserDo - UserAuthMethod IUserAuthMethodDo - UserInfoField IUserInfoFieldDo - UserRemoteLinks IUserRemoteLinksDo - UserToBeing IUserToBeingDo - UserToPronoun IUserToPronounDo - UserToRole IUserToRoleDo - UserToTag IUserToTagDo - UserToUserRelation IUserToUserRelationDo + AccessToken IAccessTokenDo + Activity IActivityDo + Collection ICollectionDo + Emote IEmoteDo + FailedOutboundRequest IFailedOutboundRequestDo + Feed IFeedDo + LoginProcessToken ILoginProcessTokenDo + MediaMetadata IMediaMetadataDo + Note INoteDo + NoteEdit INoteEditDo + NoteTag INoteTagDo + NoteToAttachment INoteToAttachmentDo + NoteToBoost INoteToBoostDo + NoteToEmote INoteToEmoteDo + NoteToFeed INoteToFeedDo + NoteToPing INoteToPingDo + Notification INotificationDo + Reaction IReactionDo + RemoteServer IRemoteServerDo + RemoteServerMetadata IRemoteServerMetadataDo + Role IRoleDo + ServerMetadata IServerMetadataDo + UnhandledMessage IUnhandledMessageDo + User IUserDo + UserAuthMethod IUserAuthMethodDo + UserInfoField IUserInfoFieldDo + UserRemoteLinks IUserRemoteLinksDo + UserToBeing IUserToBeingDo + UserToPronoun IUserToPronounDo + UserToRole IUserToRoleDo + UserToTag IUserToTagDo + UserToUserRelation IUserToUserRelationDo } func (q *Query) WithContext(ctx context.Context) *queryCtx { return &queryCtx{ - AccessToken: q.AccessToken.WithContext(ctx), - Activity: q.Activity.WithContext(ctx), - Collection: q.Collection.WithContext(ctx), - Emote: q.Emote.WithContext(ctx), - Feed: q.Feed.WithContext(ctx), - LoginProcessToken: q.LoginProcessToken.WithContext(ctx), - MediaMetadata: q.MediaMetadata.WithContext(ctx), - Note: q.Note.WithContext(ctx), - NoteEdit: q.NoteEdit.WithContext(ctx), - NoteTag: q.NoteTag.WithContext(ctx), - NoteToAttachment: q.NoteToAttachment.WithContext(ctx), - NoteToBoost: q.NoteToBoost.WithContext(ctx), - NoteToEmote: q.NoteToEmote.WithContext(ctx), - NoteToFeed: q.NoteToFeed.WithContext(ctx), - NoteToPing: q.NoteToPing.WithContext(ctx), - Notification: q.Notification.WithContext(ctx), - Reaction: q.Reaction.WithContext(ctx), - RemoteServer: q.RemoteServer.WithContext(ctx), - RemoteServerMetadata: q.RemoteServerMetadata.WithContext(ctx), - Role: q.Role.WithContext(ctx), - ServerMetadata: q.ServerMetadata.WithContext(ctx), - UnhandledMessage: q.UnhandledMessage.WithContext(ctx), - User: q.User.WithContext(ctx), - UserAuthMethod: q.UserAuthMethod.WithContext(ctx), - UserInfoField: q.UserInfoField.WithContext(ctx), - UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx), - UserToBeing: q.UserToBeing.WithContext(ctx), - UserToPronoun: q.UserToPronoun.WithContext(ctx), - UserToRole: q.UserToRole.WithContext(ctx), - UserToTag: q.UserToTag.WithContext(ctx), - UserToUserRelation: q.UserToUserRelation.WithContext(ctx), + AccessToken: q.AccessToken.WithContext(ctx), + Activity: q.Activity.WithContext(ctx), + Collection: q.Collection.WithContext(ctx), + Emote: q.Emote.WithContext(ctx), + FailedOutboundRequest: q.FailedOutboundRequest.WithContext(ctx), + Feed: q.Feed.WithContext(ctx), + LoginProcessToken: q.LoginProcessToken.WithContext(ctx), + MediaMetadata: q.MediaMetadata.WithContext(ctx), + Note: q.Note.WithContext(ctx), + NoteEdit: q.NoteEdit.WithContext(ctx), + NoteTag: q.NoteTag.WithContext(ctx), + NoteToAttachment: q.NoteToAttachment.WithContext(ctx), + NoteToBoost: q.NoteToBoost.WithContext(ctx), + NoteToEmote: q.NoteToEmote.WithContext(ctx), + NoteToFeed: q.NoteToFeed.WithContext(ctx), + NoteToPing: q.NoteToPing.WithContext(ctx), + Notification: q.Notification.WithContext(ctx), + Reaction: q.Reaction.WithContext(ctx), + RemoteServer: q.RemoteServer.WithContext(ctx), + RemoteServerMetadata: q.RemoteServerMetadata.WithContext(ctx), + Role: q.Role.WithContext(ctx), + ServerMetadata: q.ServerMetadata.WithContext(ctx), + UnhandledMessage: q.UnhandledMessage.WithContext(ctx), + User: q.User.WithContext(ctx), + UserAuthMethod: q.UserAuthMethod.WithContext(ctx), + UserInfoField: q.UserInfoField.WithContext(ctx), + UserRemoteLinks: q.UserRemoteLinks.WithContext(ctx), + UserToBeing: q.UserToBeing.WithContext(ctx), + UserToPronoun: q.UserToPronoun.WithContext(ctx), + UserToRole: q.UserToRole.WithContext(ctx), + UserToTag: q.UserToTag.WithContext(ctx), + UserToUserRelation: q.UserToUserRelation.WithContext(ctx), } } diff --git a/storage-new/dbgen/note_tags.gen.go b/storage-new/dbgen/note_tags.gen.go index 7ba03c7..ba188ab 100644 --- a/storage-new/dbgen/note_tags.gen.go +++ b/storage-new/dbgen/note_tags.gen.go @@ -30,6 +30,7 @@ func newNoteTag(db *gorm.DB, opts ...gen.DOOption) noteTag { _noteTag.ID = field.NewUint64(tableName, "id") _noteTag.NoteId = field.NewString(tableName, "note_id") _noteTag.Tag = field.NewString(tableName, "tag") + _noteTag.TagUrl = field.NewString(tableName, "tag_url") _noteTag.Note = noteTagBelongsToNote{ db: db.Session(&gorm.Session{}), @@ -411,6 +412,7 @@ type noteTag struct { ID field.Uint64 NoteId field.String Tag field.String + TagUrl field.String Note noteTagBelongsToNote fieldMap map[string]field.Expr @@ -431,6 +433,7 @@ func (n *noteTag) updateTableName(table string) *noteTag { n.ID = field.NewUint64(table, "id") n.NoteId = field.NewString(table, "note_id") n.Tag = field.NewString(table, "tag") + n.TagUrl = field.NewString(table, "tag_url") n.fillFieldMap() @@ -447,10 +450,11 @@ func (n *noteTag) GetFieldByName(fieldName string) (field.OrderExpr, bool) { } func (n *noteTag) fillFieldMap() { - n.fieldMap = make(map[string]field.Expr, 4) + n.fieldMap = make(map[string]field.Expr, 5) n.fieldMap["id"] = n.ID n.fieldMap["note_id"] = n.NoteId n.fieldMap["tag"] = n.Tag + n.fieldMap["tag_url"] = n.TagUrl } diff --git a/storage-new/dbgen/remote_servers.gen.go b/storage-new/dbgen/remote_servers.gen.go index c3861f4..3e13332 100644 --- a/storage-new/dbgen/remote_servers.gen.go +++ b/storage-new/dbgen/remote_servers.gen.go @@ -38,6 +38,8 @@ func newRemoteServer(db *gorm.DB, opts ...gen.DOOption) remoteServer { _remoteServer.Name = field.NewString(tableName, "name") _remoteServer.IconId = field.NewField(tableName, "icon_id") _remoteServer.IsSelf = field.NewBool(tableName, "is_self") + _remoteServer.LastInteraction = field.NewTime(tableName, "last_interaction") + _remoteServer.IsDead = field.NewBool(tableName, "is_dead") _remoteServer.Metadata = remoteServerHasManyMetadata{ db: db.Session(&gorm.Session{}), @@ -79,19 +81,21 @@ func newRemoteServer(db *gorm.DB, opts ...gen.DOOption) remoteServer { type remoteServer struct { remoteServerDo - ALL field.Asterisk - ID field.Uint - CreatedAt field.Time - UpdatedAt field.Time - DeletedAt field.Field - ServerType field.Field - SpecificType field.String - Version field.String - Domain field.String - Name field.String - IconId field.Field - IsSelf field.Bool - Metadata remoteServerHasManyMetadata + ALL field.Asterisk + ID field.Uint + CreatedAt field.Time + UpdatedAt field.Time + DeletedAt field.Field + ServerType field.Field + SpecificType field.String + Version field.String + Domain field.String + Name field.String + IconId field.Field + IsSelf field.Bool + LastInteraction field.Time + IsDead field.Bool + Metadata remoteServerHasManyMetadata Icon remoteServerBelongsToIcon @@ -121,6 +125,8 @@ func (r *remoteServer) updateTableName(table string) *remoteServer { r.Name = field.NewString(table, "name") r.IconId = field.NewField(table, "icon_id") r.IsSelf = field.NewBool(table, "is_self") + r.LastInteraction = field.NewTime(table, "last_interaction") + r.IsDead = field.NewBool(table, "is_dead") r.fillFieldMap() @@ -137,7 +143,7 @@ func (r *remoteServer) GetFieldByName(fieldName string) (field.OrderExpr, bool) } func (r *remoteServer) fillFieldMap() { - r.fieldMap = make(map[string]field.Expr, 13) + r.fieldMap = make(map[string]field.Expr, 15) r.fieldMap["id"] = r.ID r.fieldMap["created_at"] = r.CreatedAt r.fieldMap["updated_at"] = r.UpdatedAt @@ -149,6 +155,8 @@ func (r *remoteServer) fillFieldMap() { r.fieldMap["name"] = r.Name r.fieldMap["icon_id"] = r.IconId r.fieldMap["is_self"] = r.IsSelf + r.fieldMap["last_interaction"] = r.LastInteraction + r.fieldMap["is_dead"] = r.IsDead } diff --git a/storage-new/models/FailedOutboundRequestReason.go b/storage-new/models/FailedOutboundRequestReason.go new file mode 100644 index 0000000..4708182 --- /dev/null +++ b/storage-new/models/FailedOutboundRequestReason.go @@ -0,0 +1,19 @@ +package models + +import "regexp" + +type FailedOutboundRequestReason string + +const ( + RequestFailureNotAttemptedYet FailedOutboundRequestReason = "not attempted yet" + RequestFailureUnreachable FailedOutboundRequestReason = "target not reachable" + RequestFailureInternalError FailedOutboundRequestReason = "target internal error" + RequestFailureRejected FailedOutboundRequestReason = "request rejected" + RequestFailureRequestError FailedOutboundRequestReason = "request returned an error" + RequestFailureRateLimitedNoInfo FailedOutboundRequestReason = "request was rate-limited, no rate limit info" + RequestFailureRateLimitTemplate FailedOutboundRequestReason = "request was rate-limited: limit: %d, remaining: %d, reset: %d" +) + +var RequestFailureRateLimitRegex = regexp.MustCompile( + `request was rate-limited: limit: ([0-9\-]+), remaining: ([0-9\-]+), reset: ([0-9\-]+)`, +) diff --git a/storage-new/models/FailedOutboundRequests.go b/storage-new/models/FailedOutboundRequests.go new file mode 100644 index 0000000..421d053 --- /dev/null +++ b/storage-new/models/FailedOutboundRequests.go @@ -0,0 +1,18 @@ +package models + +import "time" + +// Stores an outbound request that hasn't successfully resolved yet +type FailedOutboundRequest struct { + Id uint64 `gorm:"primarykey"` + RawData []byte // The body data of the request + Target string // The url to send the data to (via post) + FirstAttempt time.Time // When the first attempt was started + LastAttempt time.Time // When the latest attempt was started + ActingUser *User // The user on who's behalf the request is being performed + ActingUserId string // Id of the acting user + NrOfAttempts uint32 // How often the request was attempted already + LastFailureReason string // The reason why the last attempt failed (actually a FailedOutboundRequestReason) + TargetServer *RemoteServer // The remote server being targeted. Included to determine if a request still has a chance of success + TargetServerId uint // Id of the target remote server +} diff --git a/storage-new/models/RemoteServer.go b/storage-new/models/RemoteServer.go index 659778a..3b89efb 100644 --- a/storage-new/models/RemoteServer.go +++ b/storage-new/models/RemoteServer.go @@ -2,6 +2,7 @@ package models import ( "database/sql" + "time" "gorm.io/gorm" ) @@ -11,13 +12,15 @@ import ( type RemoteServer struct { gorm.Model // The software the server is based on (Mastodon+Glitch => Mastodon, Sharkey => Misskey, Akoma => Plemora, etc) - ServerType ServerSoftwareType - SpecificType string // Specific software name (Sharkey, Iceshrimp, Akoma, etc) - Version string - Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key - Name string // What the server wants to be known as (usually same as url) - Icon *MediaMetadata // The icon used by the server. May be empty - IconId sql.NullString // ID of a media file - IsSelf bool // Whether this server is yours truly - Metadata []RemoteServerMetadata + ServerType ServerSoftwareType + SpecificType string // Specific software name (Sharkey, Iceshrimp, Akoma, etc) + Version string + Domain string // `gorm:"primaryKey"` // Domain the server exists under. Additional primary key + Name string // What the server wants to be known as (usually same as url) + Icon *MediaMetadata // The icon used by the server. May be empty + IconId sql.NullString // ID of a media file + IsSelf bool // Whether this server is yours truly + Metadata []RemoteServerMetadata // Metadata a server provides in its nodeinfo + LastInteraction time.Time // The last time the server was seen (sucessful outbound request or inbound message) + IsDead bool // Whether to consider a server dead and not bother sending anything anymore } diff --git a/web/shared/clientRfc9421.go b/web/shared/clientRfc9421.go index 187be1d..fd6b526 100644 --- a/web/shared/clientRfc9421.go +++ b/web/shared/clientRfc9421.go @@ -2,12 +2,17 @@ package webshared import ( "bytes" + "cmp" "crypto/sha256" "crypto/x509" "encoding/base64" + "fmt" "io" "net/http" + "net/url" "slices" + "strconv" + "strings" "time" "github.com/rs/zerolog/log" @@ -15,6 +20,7 @@ import ( "git.mstar.dev/mstar/linstrom/config" "git.mstar.dev/mstar/linstrom/shared" + "git.mstar.dev/mstar/linstrom/storage-new/dbgen" "git.mstar.dev/mstar/linstrom/storage-new/models" ) @@ -41,13 +47,22 @@ func RequestSigned( body []byte, actor *models.User, ) (response *http.Response, wasRfc9421 bool, err error) { - res, err := RequestSignedRFC9421(method, target, body, actor) - if err == nil && res.StatusCode >= 200 && res.StatusCode < 400 { - return res, true, nil + if method == "POST" { + storedRequestId, err := prePostRequest(target, body, actor) + if err != nil { + return nil, false, err + } + defer postPostRequest(response, err, *storedRequestId) } + wasRfc9421 = true + response, err = RequestSignedRFC9421(method, target, body, actor) + if err == nil && response.StatusCode < 400 { + return + } + wasRfc9421 = false log.Debug().Str("target", target).Msg("RFC9421 signed request failed, trying cavage signed") - res, err = RequestSignedCavage(method, target, body, actor) - return res, false, err + response, err = RequestSignedCavage(method, target, body, actor) + return } // Perform a request, signing it as specified in RFC 9421 @@ -155,3 +170,130 @@ func applyBodyHash(headers http.Header, body []byte) error { headers.Set("Digest", header) return nil } + +// Runs before a signed outbound request. +// If the request is POST, stores it in the db as not processed yet. +// This is to ensure data consistency +func prePostRequest( + method, target string, + body []byte, + actor *models.User, +) (*uint64, error) { + targetUrl, err := url.Parse(target) + if err != nil { + return nil, err + } + server, err := dbgen.RemoteServer.Where(dbgen.RemoteServer.Domain.Eq(targetUrl.Hostname())). + First() + if err != nil { + return nil, err + } + fr := dbgen.FailedOutboundRequest + now := time.Now() + data := models.FailedOutboundRequest{ + TargetServer: server, + TargetServerId: server.ID, + ActingUserId: actor.ID, + ActingUser: actor, + NrOfAttempts: 1, + RawData: body, + FirstAttempt: now, + LastAttempt: now, + LastFailureReason: string(models.RequestFailureNotAttemptedYet), + } + err = fr.Create(&data) + if err != nil { + return nil, err + } + return &data.Id, nil +} + +// Updates the db request based on the results of the request +func postPostRequest(resp *http.Response, reqErr error, dbId uint64) { + fr := dbgen.FailedOutboundRequest + failureReason := "generic" + update := true // Flag to tell defer func to not update since request info has been deleted + defer func() { + if !update { + return + } + _, err := fr.Where(fr.Id.Eq(dbId)).UpdateColumn(fr.LastFailureReason, failureReason) + if err != nil { + log.Error(). + Err(err). + Str("reason", failureReason). + Uint64("request-id", dbId). + Msg("Failed to update failure reason") + } + }() + if reqErr != nil { + failureReason = string(models.RequestFailureRequestError) + return + } + // Only check response data after handling response error + // Response could be nil otherwise, causing a panic (or an extra, useless check) + + // If response status is ok (< 400) delete entry in db to not process it again + if resp.StatusCode < 400 { + update = false + fr.Where(fr.Id.Eq(dbId)).Delete() + return + } + if resp.StatusCode == 429 { + // Always prefer the rate limit headers as defined by https://www.ietf.org/archive/id/draft-polli-ratelimit-headers-02.html + limit := cmp.Or( + resp.Header.Get("RateLimit-Limit"), + resp.Header.Get("X-RateLimit-Limit"), + resp.Header.Get("X-Rate-Limit-Limit"), + ) + remaining := cmp.Or( + resp.Header.Get("RateLimit-Remaining"), + resp.Header.Get("X-RateLimit-Remaining"), + resp.Header.Get("X-Rate-Limit-Remaining"), + ) + reset := cmp.Or( + resp.Header.Get("RateLimit-Reset"), + resp.Header.Get("X-RateLimit-Reset"), + resp.Header.Get("X-Rate-Limit-Reset"), + ) + if cmp.Or(limit, remaining, reset) == "" { + failureReason = string(models.RequestFailureRateLimitedNoInfo) + return + } else { + limit = strings.Split(limit, ",")[0] + limit = strings.Split(limit, ";")[0] + if limit == "" { + limit = "-1" + } + limitNum, err := strconv.Atoi(limit) + if err != nil { + failureReason = string(models.RequestFailureRateLimitedNoInfo) + return + } + if remaining == "" { + remaining = "-1" + } + remainingNum, err := strconv.Atoi(remaining) + if err != nil { + failureReason = string(models.RequestFailureRateLimitedNoInfo) + return + } + if reset == "" { + reset = "-1" + } + resetNum, err := strconv.Atoi(reset) + if err != nil { + failureReason = string(models.RequestFailureRateLimitedNoInfo) + return + } + failureReason = fmt.Sprintf(string(models.RequestFailureRateLimitTemplate), limitNum, remainingNum, resetNum) + } + return + } else { + if resp.StatusCode >= 500 { + failureReason = string(models.RequestFailureInternalError) + } else { + failureReason = string(models.RequestFailureRejected) + } + } +}