feat: live module and jenkins pipeline to harbor deploy

This commit is contained in:
Yvan
2026-09-21 16:45:44 +08:00
parent 451c8e2abc
commit 829d75c657
145 changed files with 8984 additions and 269 deletions
+130
View File
@@ -0,0 +1,130 @@
package live
import (
"context"
"sort"
"sync"
"time"
bizlive "kra/internal/biz/live"
)
type streamState struct {
stream *bizlive.Stream
users map[uint]struct{}
}
type streamRepo struct {
mu sync.RWMutex
streams map[string]*streamState
}
func NewStreamRepo() bizlive.StreamRepo {
return &streamRepo{streams: make(map[string]*streamState)}
}
func (r *streamRepo) Get(_ context.Context, streamID string) (*bizlive.Stream, error) {
r.mu.RLock()
defer r.mu.RUnlock()
state := r.streams[streamID]
if state == nil {
return &bizlive.Stream{StreamID: streamID, UpdatedAt: time.Now()}, nil
}
return clone(state.stream), nil
}
func (r *streamRepo) List(_ context.Context) ([]*bizlive.Stream, error) {
r.mu.RLock()
defer r.mu.RUnlock()
items := make([]*bizlive.Stream, 0, len(r.streams))
for _, state := range r.streams {
if state.stream.PublisherOnline {
items = append(items, clone(state.stream))
}
}
sort.Slice(items, func(i, j int) bool { return items[i].StreamID < items[j].StreamID })
return items, nil
}
func (r *streamRepo) RegisterPublisher(_ context.Context, streamID string, userID uint) (*bizlive.Stream, error) {
r.mu.Lock()
defer r.mu.Unlock()
state := r.streams[streamID]
if state == nil {
if len(r.streams) >= bizlive.MaxStreams {
return nil, bizlive.ErrMaxStreams
}
state = &streamState{stream: &bizlive.Stream{StreamID: streamID}, users: make(map[uint]struct{})}
r.streams[streamID] = state
}
if state.stream.PublisherOnline {
return nil, bizlive.ErrPublisherExists
}
state.stream.PublisherID = userID
state.stream.PublisherOnline = true
state.stream.UpdatedAt = time.Now()
return clone(state.stream), nil
}
func (r *streamRepo) UnregisterPublisher(_ context.Context, streamID string, userID uint) error {
r.mu.Lock()
defer r.mu.Unlock()
state := r.streams[streamID]
if state == nil || !state.stream.PublisherOnline || state.stream.PublisherID != userID {
return bizlive.ErrPublisherNotFound
}
state.stream.PublisherID = 0
state.stream.PublisherOnline = false
state.stream.UpdatedAt = time.Now()
if len(state.users) == 0 {
delete(r.streams, streamID)
}
return nil
}
func (r *streamRepo) RegisterSubscriber(_ context.Context, streamID string, userID uint) (*bizlive.Stream, error) {
r.mu.Lock()
defer r.mu.Unlock()
state := r.streams[streamID]
if state == nil {
if len(r.streams) >= bizlive.MaxStreams {
return nil, bizlive.ErrMaxStreams
}
state = &streamState{stream: &bizlive.Stream{StreamID: streamID}, users: make(map[uint]struct{})}
r.streams[streamID] = state
}
if _, exists := state.users[userID]; exists {
return nil, bizlive.ErrSubscriberExists
}
state.users[userID] = struct{}{}
state.stream.SubscriberCount = len(state.users)
state.stream.UpdatedAt = time.Now()
return clone(state.stream), nil
}
func (r *streamRepo) UnregisterSubscriber(_ context.Context, streamID string, userID uint) error {
r.mu.Lock()
defer r.mu.Unlock()
state := r.streams[streamID]
if state == nil {
return bizlive.ErrSubscriberNotFound
}
if _, exists := state.users[userID]; !exists {
return bizlive.ErrSubscriberNotFound
}
delete(state.users, userID)
state.stream.SubscriberCount = len(state.users)
state.stream.UpdatedAt = time.Now()
if !state.stream.PublisherOnline && len(state.users) == 0 {
delete(r.streams, streamID)
}
return nil
}
func clone(stream *bizlive.Stream) *bizlive.Stream {
if stream == nil {
return nil
}
value := *stream
return &value
}