package usecase import ( "context" "errors" "fmt" "math/rand" "sync" ) const ( MaxSimultaneousTestingProcesses = 5000 MaxMessagesPerSolution = 500 ) type TesterUseCase struct { publicChannels sync.Map privateChannels sync.Map testingChannel chan int32 } func NewTesterUseCase() *TesterUseCase { return &TesterUseCase{ testingChannel: make(chan int32, MaxSimultaneousTestingProcesses), } } func (u *TesterUseCase) CreateSolution(ctx context.Context, taskId int32, solution string, language int32) (int32, error) { return rand.Int31(), nil } func (u *TesterUseCase) ProcessTesting(ctx context.Context, solutionId int32) (<-chan string, error) { u.testingChannel <- solutionId publicChannel := u.newPublicChannel(solutionId) go func() { privateChannel := u.newPrivateChannel(solutionId) defer func() { err := u.closeAndDeletePrivateChannel(solutionId) if err != nil { panic(err) } err = u.closeAndDeletePublicChannel(solutionId) if err != nil { panic(err) } }() c := 0 for res := range privateChannel { c += 1 publicChannel <- res if c == 15 { fmt.Println("finished") break } } }() return publicChannel, nil } func (u *TesterUseCase) ProcessResult(ctx context.Context, solutionId int32, result string) error { ch, ok := u.privateChannels.Load(solutionId) if !ok { return errors.New("") } ch.(chan string) <- result return nil } func (u *TesterUseCase) TestingChannel() chan int32 { return u.testingChannel } func (u *TesterUseCase) newPublicChannel(solutionId int32) chan string { userCh := make(chan string, MaxMessagesPerSolution) u.publicChannels.Store(solutionId, userCh) return userCh } func (u *TesterUseCase) newPrivateChannel(solutionId int32) chan string { userCh := make(chan string, MaxMessagesPerSolution) u.privateChannels.Store(solutionId, userCh) return userCh } func (u *TesterUseCase) closeAndDeletePublicChannel(solutionId int32) error { ch, ok := u.publicChannels.Load(solutionId) if !ok { return errors.New("") } close(ch.(chan string)) u.publicChannels.Delete(solutionId) return nil } func (u *TesterUseCase) closeAndDeletePrivateChannel(solutionId int32) error { ch, ok := u.privateChannels.Load(solutionId) if !ok { return errors.New("") } close(ch.(chan string)) u.privateChannels.Delete(solutionId) return nil }