func (cmd *serveEmbedCmd) run(ctx scope.Context, args []string) error { listener, err := net.Listen("tcp", cmd.addr) if err != nil { return err } closed := false m := sync.Mutex{} closeListener := func() { m.Lock() if !closed { listener.Close() closed = true } m.Unlock() } // Spin off goroutine to watch ctx and close listener if shutdown requested. go func() { <-ctx.Done() closeListener() }() if err := http.Serve(listener, cmd); err != nil { fmt.Printf("http[%s]: %s\n", cmd.addr, err) return err } closeListener() ctx.WaitGroup().Done() return ctx.Err() }
func (ctrl *Controller) terminal(ctx scope.Context, ch ssh.Channel) { defer ch.Close() lines := make(chan string) term := terminal.NewTerminal(ch, "> ") go func() { for ctx.Err() == nil { line, err := term.ReadLine() if err != nil { ctx.Terminate(err) return } lines <- line } }() for { var line string select { case <-ctx.Done(): return case line = <-lines: } cmd := parse(line) fmt.Printf("[control] > %v\n", cmd) switch cmd[0] { case "": continue case "quit": return case "shutdown": ctrl.ctx.Terminate(fmt.Errorf("shutdown initiated from console")) default: runCommand(ctx.Fork(), ctrl, cmd[0], term, cmd[1:]) } } }
func (jq *JobQueueBinding) WaitForJob(ctx scope.Context) error { ch := make(chan error) // background goroutine to wait on condition go func() { // synchronize with caller <-ch jq.m.Unlock() jq.Backend.jobQueueListener().wait(jq.Name()) ch <- nil }() // synchronize with background goroutine jq.m.Lock() ch <- nil jq.m.Lock() jq.m.Unlock() select { case <-ctx.Done(): jq.Backend.jobQueueListener().wakeAll(jq.Name()) <-ch return ctx.Err() case err := <-ch: return err } }
func Claim(ctx scope.Context, jq JobQueue, handlerID string, pollTime time.Duration, stealChance float64) (*Job, error) { for ctx.Err() == nil { if rand.Float64() < stealChance { job, err := jq.TrySteal(ctx, handlerID) if err != nil && err != ErrJobNotFound { return nil, err } if err == nil { return job, nil } } job, err := jq.TryClaim(ctx, handlerID) if err != nil { if err == ErrJobNotFound { child := ctx.ForkWithTimeout(pollTime) if err = jq.WaitForJob(child); err != nil && err != scope.TimedOut { return nil, err } continue } return nil, err } return job, nil } return nil, ctx.Err() }
func (s *session) Send(ctx scope.Context, cmdType proto.PacketType, payload interface{}) error { // Special case: certain events have privileged info that may need to be stripped from them switch event := payload.(type) { case *proto.PresenceEvent: switch s.privilegeLevel() { case proto.Staff: case proto.Host: event.RealClientAddress = "" default: event.RealClientAddress = "" event.ClientAddress = "" } case *proto.Message: if s.privilegeLevel() == proto.General { event.Sender.ClientAddress = "" } case *proto.EditMessageEvent: if s.privilegeLevel() == proto.General { event.Sender.ClientAddress = "" } } var err error payload, err = proto.DecryptPayload(payload, &s.client.Authorization, s.privilegeLevel()) if err != nil { return err } encoded, err := json.Marshal(payload) if err != nil { return err } cmd := &proto.Packet{ Type: cmdType, Data: encoded, } // Add to outgoing channel. If channel is full, defer to goroutine so as not to block // the caller (this may result in deliveries coming out of order). select { case <-ctx.Done(): // Session is closed, return error. return ctx.Err() case s.outgoing <- cmd: // Packet delivered to queue. default: // Queue is full. logging.Logger(s.ctx).Printf("outgoing channel full, ordering cannot be guaranteed") go func() { s.outgoing <- cmd }() } return nil }
func Loop(ctx scope.Context, heim *proto.Heim, workerName, queueName string) error { fmt.Printf("Loop\n") ctrl, err := NewController(ctx, heim, workerName, queueName) if err != nil { fmt.Printf("error: %s\n", err) return err } ctx.WaitGroup().Add(1) go ctrl.background(ctx) ctx.WaitGroup().Wait() return ctx.Err() }
func (jq *JobQueue) WaitForJob(ctx scope.Context) error { ch := make(chan error) go func() { jq.m.Lock() jq.c.Wait() jq.m.Unlock() ch <- nil }() select { case <-ctx.Done(): jq.m.Lock() jq.c.Broadcast() jq.m.Unlock() <-ch return ctx.Err() case err := <-ch: return err } }