179 lines
4.4 KiB
Go
179 lines
4.4 KiB
Go
package l_export_async
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
)
|
|
|
|
// PageStrategyType 分页策略类型
|
|
type PageStrategyType string
|
|
|
|
const (
|
|
PageStrategyOffset PageStrategyType = "offset"
|
|
PageStrategyCursor PageStrategyType = "cursor"
|
|
PageStrategyTime PageStrategyType = "time"
|
|
)
|
|
|
|
// PageStrategy 分页策略接口
|
|
type PageStrategy interface {
|
|
// Type 类型标识
|
|
Type() PageStrategyType
|
|
|
|
// InitialState 获取初始状态
|
|
InitialState() interface{}
|
|
|
|
// NextPage 获取下一页数据
|
|
NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error)
|
|
|
|
// HasMore 是否还有下一页
|
|
HasMore(state interface{}, lastData [][]interface{}) bool
|
|
|
|
// GetLimit 获取每批数据量
|
|
GetLimit() int
|
|
}
|
|
|
|
// DataFetcher 数据获取函数类型
|
|
type (
|
|
// OffsetDataFetcher 传统分页
|
|
OffsetDataFetcher func(ctx context.Context, pageNum, limit int) ([][]interface{}, error)
|
|
|
|
// CursorDataFetcher 游标分页
|
|
CursorDataFetcher func(ctx context.Context, cursor interface{}, limit int) ([][]interface{}, interface{}, error)
|
|
|
|
// TimeRangeDataFetcher 时间范围分页
|
|
TimeRangeDataFetcher func(ctx context.Context, startTime time.Time, limit int) ([][]interface{}, error)
|
|
)
|
|
|
|
// OffsetStrategy 传统分页策略
|
|
type OffsetStrategy struct {
|
|
fetcher OffsetDataFetcher
|
|
limit int
|
|
total int // 可选,用于提前知道总数
|
|
}
|
|
|
|
func (s *OffsetStrategy) Type() PageStrategyType {
|
|
return PageStrategyOffset
|
|
}
|
|
|
|
func (s *OffsetStrategy) InitialState() interface{} {
|
|
return 1 // 初始页码
|
|
}
|
|
|
|
func (s *OffsetStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) {
|
|
pageNum := state.(int)
|
|
data, err := s.fetcher(ctx, pageNum, s.limit)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// 下一页页码
|
|
nextState := pageNum + 1
|
|
|
|
return data, nextState, nil
|
|
}
|
|
|
|
func (s *OffsetStrategy) HasMore(state interface{}, lastData [][]interface{}) bool {
|
|
if s.total > 0 {
|
|
currentPage := state.(int)
|
|
totalPages := (s.total + s.limit - 1) / s.limit
|
|
return currentPage <= totalPages
|
|
}
|
|
|
|
// 如果没有总数,则根据最后一页数据判断
|
|
//return len(lastData) >= s.limit
|
|
//这里改为判断是否为空,多查一次
|
|
|
|
return len(lastData) > 0
|
|
}
|
|
|
|
func (s *OffsetStrategy) GetLimit() int {
|
|
return s.limit
|
|
}
|
|
|
|
// CursorStrategy 游标分页策略
|
|
type CursorStrategy struct {
|
|
fetcher CursorDataFetcher
|
|
limit int
|
|
initialCursor interface{}
|
|
}
|
|
|
|
func (s *CursorStrategy) Type() PageStrategyType {
|
|
return PageStrategyCursor
|
|
}
|
|
|
|
func (s *CursorStrategy) InitialState() interface{} {
|
|
return s.initialCursor // nil 或初始游标值
|
|
}
|
|
|
|
func (s *CursorStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) {
|
|
return s.fetcher(ctx, state, s.limit)
|
|
}
|
|
|
|
func (s *CursorStrategy) HasMore(state interface{}, lastData [][]interface{}) bool {
|
|
// 这里如果为空,证明已经到最后一夜了
|
|
return len(lastData) > 0
|
|
}
|
|
|
|
func (s *CursorStrategy) GetLimit() int {
|
|
return s.limit
|
|
}
|
|
|
|
// TimeRangeStrategy 时间范围分页策略
|
|
type TimeRangeStrategy struct {
|
|
fetcher TimeRangeDataFetcher
|
|
limit int
|
|
startTime time.Time
|
|
endTime time.Time // 可选的结束时间
|
|
timeRange time.Duration // 每次查询的时间范围
|
|
lastQueryTime *time.Time // 记录最后一次查询的时间
|
|
}
|
|
|
|
func (s *TimeRangeStrategy) Type() PageStrategyType {
|
|
return PageStrategyTime
|
|
}
|
|
|
|
func (s *TimeRangeStrategy) InitialState() interface{} {
|
|
return s.startTime
|
|
}
|
|
|
|
func (s *TimeRangeStrategy) NextPage(ctx context.Context, state interface{}) ([][]interface{}, interface{}, error) {
|
|
currentTime := state.(time.Time)
|
|
|
|
// 如果设置了结束时间,且当前时间已经超过结束时间
|
|
if !s.endTime.IsZero() && currentTime.After(s.endTime) {
|
|
return nil, currentTime, nil
|
|
}
|
|
|
|
data, err := s.fetcher(ctx, currentTime, s.limit)
|
|
if err != nil {
|
|
return nil, nil, err
|
|
}
|
|
|
|
// 更新时间状态
|
|
var nextTime time.Time
|
|
if len(data) > 0 {
|
|
// 这里假设数据按时间排序,可以通过自定义逻辑来调整
|
|
nextTime = currentTime.Add(s.timeRange)
|
|
} else {
|
|
nextTime = currentTime.Add(s.timeRange)
|
|
}
|
|
|
|
s.lastQueryTime = ¤tTime
|
|
return data, nextTime, nil
|
|
}
|
|
|
|
func (s *TimeRangeStrategy) HasMore(state interface{}, lastData [][]interface{}) bool {
|
|
currentTime := state.(time.Time)
|
|
|
|
// 如果设置了结束时间
|
|
if !s.endTime.IsZero() {
|
|
return currentTime.Before(s.endTime)
|
|
}
|
|
|
|
return len(lastData) > 0
|
|
}
|
|
|
|
func (s *TimeRangeStrategy) GetLimit() int {
|
|
return s.limit
|
|
}
|