package f5 import ( "q5" "os" "time" "sync" "errors" "gorm.io/gorm" "net/http" "github.com/gin-gonic/gin" ) const ( ONLINE_ENV = 0 TEST_ENV = iota DEV_ENV = iota ) var serverEnv int32 var globalLock sync.Mutex var globalLockHash map[string]*sync.Mutex func IsTestEnv() bool { return serverEnv == TEST_ENV } func IsOnlineEnv() bool { return serverEnv == ONLINE_ENV } func IsDevEnv() bool { return serverEnv == DEV_ENV } func New[T any](cb func(*T)) *T { obj := new(T) cb(obj) return obj } func ExtractRegisterTimeFromSessionId(sessionId string) int32 { strList := q5.StrSplit(sessionId, "_") if len(strList) < 4 { return 0 } return q5.ToInt32(strList[0]) } func IsOrmErrRecordNotFound(err error) bool { return errors.Is(err, gorm.ErrRecordNotFound) } func AllocLock(key string) *sync.Mutex { var l *sync.Mutex globalLock.Lock() if p, ok := globalLockHash[key]; ok { l = p } else { l = new(sync.Mutex) globalLockHash[key] = l } globalLock.Unlock() go func () { time.Sleep(time.Second * 30) globalLock.Lock() delete(globalLockHash, key) globalLock.Unlock() }() l.Lock() return l } func ReleaseLock(l *sync.Mutex) { l.Unlock() } func BatchAllocLock(keys []string) []*sync.Mutex { locks := []*sync.Mutex{} lock := sync.Mutex{} for _, key := range keys { go func () { l := AllocLock(key) lock.Lock() q5.AppendSlice(&locks, l) lock.Unlock() }() } for len(locks) < len(keys) { time.Sleep(time.Millisecond * 10) } return locks } func BatchReleaseLock(locks []*sync.Mutex) { for _, val := range locks { ReleaseLock(val) } } func RspErr(c *gin.Context, errCode int32, errMsg string) { c.JSON(http.StatusOK, gin.H{ "errcode": errCode, "errmsg": errMsg, }) } func RspErr2(c *gin.Context, code int32, message string) { c.JSON(http.StatusOK, gin.H{ "code": code, "message": message, }) } func DataSetStreamPageQuery(dataSet []interface{}, pageSize int32, cursor int64, filterCb func(interface{}) bool, orderByCb func(interface{}, interface{}) bool, queryCb func(*StreamPagination), fillCb func(interface{})) { if pageSize <= 0 { pageSize = 1 } if pageSize > 1000 { pageSize = 1000 } if cursor < 1 { cursor = 1 } if cursor > 10000 { cursor = 10000 } var dataSetCopy []*interface{} q5.NewSlice(&dataSetCopy, 0, int32(len(dataSet))) for _, val := range dataSet { tmpVal := val if filterCb(val) { q5.AppendSlice(&dataSetCopy, &tmpVal) } } q5.Sort(dataSetCopy, func(a *interface{}, b *interface{}) bool { return orderByCb(*a, *b) }) var pagination StreamPagination pagination.NextCursor = cursor if int64(pageSize) * cursor < int64(len(dataSetCopy)) { pagination.NextCursor = cursor + 1 pagination.Remaining = 1 } pagination.PreviousCursor = q5.Max(1, cursor - 1) pagination.Count = int32(int64(len(dataSetCopy)) - int64(pageSize) * (cursor - 1)) if pagination.Count < 0 { pagination.Count = 0 } else { pagination.Count = q5.Min(pageSize, pagination.Count) } pagination.TotalCount = int32(len(dataSetCopy)) queryCb(&pagination) var count int32 startIdx := int(int64(pageSize) * (cursor - 1)) for i := startIdx; i < len(dataSetCopy); i++ { fillCb(*dataSetCopy[i]) count++ if count >= pagination.Count { break } } } func init() { switch os.Getenv("SERVER_ENV") { case "TEST": serverEnv = TEST_ENV case "DEBUG": serverEnv = DEV_ENV default: serverEnv = ONLINE_ENV } globalLockHash = map[string]*sync.Mutex{} }