Documentation
¶
Index ¶
- type Directory
- type Osu
- func (o *Osu) GetBackgroundFile(path string) ([]byte, error)
- func (o *Osu) GetBackgroundFilePath(beatmapId int32) string
- func (o *Osu) GetBeatmapByDifficultyId(difficultyId int32) (*osu.Beatmap, error)
- func (o *Osu) GetBeatmaps() []osu.DatabaseBeatmap
- func (o *Osu) GetOsuFilePath(bm osu.DatabaseBeatmap) string
- func (o *Osu) GetTrackPathByDifficultyId(ctx context.Context, difficultyId int32) (string, error)
- func (o *Osu) GetUserID(username string) (int, error)
- func (o *Osu) ParseBeatmapFile(bm osu.DatabaseBeatmap) (*osu.Beatmap, error)
- func (o *Osu) ReadOsuDBFile() error
- type OsuSkins
- type ProgressEvent
- type ProgressStage
- type Syncer
- type SyncerOption
Constants ¶
This section is empty.
Variables ¶
This section is empty.
Functions ¶
This section is empty.
Types ¶
type Osu ¶
type Osu struct {
BeatmapDifficultyIndex map[int32]map[int32]int
BeatmapByDifficultyId map[int32]int32
Logger *slog.Logger
// contains filtered or unexported fields
}
func NewOsuService ¶
func (*Osu) GetBackgroundFilePath ¶
func (*Osu) GetBeatmapByDifficultyId ¶
func (*Osu) GetBeatmaps ¶
func (o *Osu) GetBeatmaps() []osu.DatabaseBeatmap
func (*Osu) GetOsuFilePath ¶
func (o *Osu) GetOsuFilePath(bm osu.DatabaseBeatmap) string
func (*Osu) GetTrackPathByDifficultyId ¶
func (*Osu) ParseBeatmapFile ¶
func (*Osu) ReadOsuDBFile ¶
type ProgressEvent ¶
type ProgressEvent struct {
Stage ProgressStage `json:"stage"`
Table string `json:"table,omitempty"` // set on StageWrite: "beatmapsets" | "beatmaps" | "skill_cache"
Done int64 `json:"done"`
Total int64 `json:"total"`
Message string `json:"message,omitempty"`
Err string `json:"error,omitempty"`
At time.Time `json:"at"`
}
ProgressEvent is a single unit of live sync progress, meant to be forwarded to a frontend (e.g. published over the realtime websocket hub).
This intentionally carries only beatmap-level counts, not per-file or per-mod-combination detail (there's no BeatmapID/Mods field) — at 16k beatmaps × 36 mod combinations, anything finer-grained is 576k+ events for a single sync run, which floods the frontend far faster than a progress bar can usefully render and was observed to make the browser tab unresponsive. "N of 16000 beatmaps done" is all a human watching a progress bar actually needs. Emission is also rate-limited — see emitThrottled — so even StageCalcProgress/StageWrite fire at most a couple of times a second, not once per completed unit of work.
type ProgressStage ¶
type ProgressStage string
ProgressStage identifies which phase of the sync a ProgressEvent describes. Deliberately coarse — see the package-level comment on ProgressEvent for why per-beatmap/per-mod-combination detail was cut.
const ( StageReadDB ProgressStage = "read_db" // osu!.db parsed into raw rows StageDiff ProgressStage = "diff" // MD5 diff against stored beatmaps done StageCalcProgress ProgressStage = "calc_progress" // N/total beatmaps fully calculated (skill math for all mod combinations) StageWrite ProgressStage = "write" // a db upsert batch was flushed StageDone ProgressStage = "done" // Run() finished )
type Syncer ¶
type Syncer struct {
// contains filtered or unexported fields
}
func NewSyncer ¶
func NewSyncer(osuSvc *Osu, repos *repository.Repos, logger *slog.Logger, opts ...SyncerOption) *Syncer
NewSyncer requires an explicit logger rather than reaching into Osu's internal one — if you don't see sync logs, check what's passed here first (nil logger, or one configured below Info level, are the usual culprits).
func (*Syncer) Run ¶
Run performs a full sync pass:
- parse osu!.db
- map rows into model.BeatmapSet / model.Beatmap
- diff MD5 hashes against what's already stored to find changed/new maps
- for changed maps only: parse the .osu file and compute Skills for every mod combination via skills.ProcessBeatmap
- persist everything, then drop rows for maps no longer present
type SyncerOption ¶
type SyncerOption func(*Syncer)
func WithConcurrency ¶
func WithConcurrency(n int) SyncerOption
func WithProgress ¶
func WithProgress(ch chan<- ProgressEvent) SyncerOption
WithProgress attaches a channel that Syncer publishes ProgressEvent values to as it works. Sends are non-blocking — if the channel is full, the event is dropped rather than stalling the sync. Give the channel a reasonable buffer (e.g. 1024) and a goroutine that drains it promptly.
func WithSkillCalcTimeout ¶
func WithSkillCalcTimeout(d time.Duration) SyncerOption