// Test the creation of identifiers based on parts. func TestIdentifier(t *testing.T) { assert := audit.NewTestingAssertion(t, true) // Identifier. id := identifier.Identifier("One", 2, "three four") assert.Equal(id, "one:2:three-four", "wrong Identifier() result") id = identifier.Identifier(2011, 6, 22, "One, two, or three things.") assert.Equal(id, "2011:6:22:one-two-or-three-things", "wrong Identifier() result") }
func addRoom(env cells.Environment, buildingName string, roomName string) { r := newRoom(roomName, buildingName, []string{"hell"}) roomID := identifier.Identifier("room", buildingName, roomName) env.StartCell(roomID, r) paID := identifier.Identifier("building", buildingName, "pa") subscribe(env, paID, roomID) env.EmitNew(identifier.Identifier("building", buildingName), ROOM_ADDED, cells.PayloadValues{ "room": roomID, }, nil) }
func (r *room) Init(ctx cells.Context) (err error) { r.ctx = ctx r.censorID = identifier.Identifier("room", r.buildingName, r.name, "censor") r.censor = newCensor(r.censorID, r.censoredWords) // TODO: hangs without goroutine go func() { roomID := identifier.Identifier("room", r.buildingName, r.name) env := r.ctx.Environment() env.StartCell(r.censorID, r.censor) subscribe(env, r.censorID, roomID) }() return }
func wsRoomHandler(w http.ResponseWriter, r *http.Request) { user := r.URL.Query().Get("user") if user == "" || user == "undefined" { http.Error(w, "user name not specified", http.StatusTeapot) return } vars := mux.Vars(r) building := vars["building"] room := vars["room"] roomID := makeRoomID(room, building) ws, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Fatal(err) } wsb := newWebSocketBehavior(ws, user) id := identifier.Identifier("wsb", user, identifier.NewUUID()) rootEnvironment.StartCell(id, wsb) subscribe(rootEnvironment, roomID, id) userID := addUser(rootEnvironment, building, room, user) defer func() { wsb.sendUserLeaveEvent() rootEnvironment.StopCell(userID) rootEnvironment.StopCell(id) }() go wsb.writePump() wsb.readPump() }
// newCell create a new cell around a behavior. func newCell(env *environment, id string, behavior Behavior) (*cell, error) { logger.Infof("cell '%s' starts", id) // Init cell runtime. c := &cell{ env: env, id: id, measuringID: identifier.Identifier("cells", env.id, "cell", id), behavior: behavior, emitters: newConnections(), subscribers: newConnections(), emitTimeoutTicker: time.NewTicker(5 * time.Second), } // Set configuration. if bebs, ok := behavior.(BehaviorEventBufferSize); ok { size := bebs.EventBufferSize() if size < minEventBufferSize { size = minEventBufferSize } c.eventc = make(chan Event, size) } else { c.eventc = make(chan Event, minEventBufferSize) } if brf, ok := behavior.(BehaviorRecoveringFrequency); ok { number, duration := brf.RecoveringFrequency() if duration.Seconds()/float64(number) < 0.1 { number = minRecoveringNumber duration = minRecoveringDuration } c.recoveringNumber = number c.recoveringDuration = duration } else { c.recoveringNumber = minRecoveringNumber c.recoveringDuration = minRecoveringDuration } if bet, ok := behavior.(BehaviorEmitTimeout); ok { timeout := bet.EmitTimeout() switch { case timeout < minEmitTimeout: timeout = minEmitTimeout case timeout > maxEmitTimeout: timeout = maxEmitTimeout } c.emitTimeout = int(timeout.Seconds() / 5) } else { c.emitTimeout = int(maxEmitTimeout.Seconds() / 5) } // Init behavior. if err := behavior.Init(c); err != nil { return nil, errors.Annotate(err, ErrCellInit, errorMessages, id) } // Start backend. c.loop = loop.GoRecoverable(c.backendLoop, c.checkRecovering, id) return c, nil }
func addLogUser(env cells.Environment, buildingName string, roomName string) { roomID := identifier.Identifier("room", buildingName, roomName) userID := makeUserID("logger") lu := &logUser{} lu.name = "logger" env.StartCell(userID, lu) subscribe(env, roomID, userID) env.EmitNew(roomID, "user-added", cells.PayloadValues{ "user": userID, }, nil) }
func addUser(env cells.Environment, buildingName string, roomName string, userName string) string { roomID := identifier.Identifier("room", buildingName, roomName) userID := makeUserID(userName) u := newUser(userName) env.StartCell(userID, u) subscribe(env, roomID, userID) env.EmitNew(roomID, USER_ADDED, cells.PayloadValues{ "user": userID, }, nil) return userID }
// NewEnvironment creates a new environment. func NewEnvironment(idParts ...interface{}) Environment { var id string if len(idParts) == 0 { id = identifier.NewUUID().String() } else { id = identifier.Identifier(idParts...) } env := &environment{ id: id, cells: newRegistry(), } runtime.SetFinalizer(env, (*environment).Stop) logger.Infof("cells environment %q started", env.ID()) return env }
// backendLoop is the backend for the processing of messages. func (c *cell) backendLoop(l loop.Loop) error { monitoring.IncrVariable(identifier.Identifier("cells", c.env.ID(), "total-cells")) defer monitoring.DecrVariable(identifier.Identifier("cells", c.env.ID(), "total-cells")) for { select { case <-l.ShallStop(): return c.behavior.Terminate() case subscribers := <-c.subscriberc: c.subscribers = subscribers case event := <-c.eventc: if event == nil { panic("received illegal nil event!") } measuring := monitoring.BeginMeasuring(c.measuringID) err := c.behavior.ProcessEvent(event) if err != nil { c.loop.Kill(err) continue } measuring.EndMeasuring() } } }
func addBuilding(env cells.Environment, buildingName string) string { b := &building{ name: buildingName, rooms: make(map[string]bool), } buildingID := makeBuildingID(buildingName) env.StartCell(buildingID, b) pa := &publicAddress{interval: time.Second * 10} paID := identifier.Identifier("building", buildingName, "pa") env.StartCell(paID, pa) subscribe(env, paID, buildingID) return buildingID }
// Do executes one Redis command and returns // the result as result set. func (conn *Connection) Do(cmd string, args ...interface{}) (*ResultSet, error) { cmd = strings.ToLower(cmd) if strings.Contains(cmd, "subscribe") { return nil, errors.New(ErrUseSubscription, errorMessages) } err := conn.ensureProtocol() if err != nil { return nil, err } if conn.database.monitoring { m := monitoring.BeginMeasuring(identifier.Identifier("redis", "command", cmd)) defer m.EndMeasuring() } err = conn.resp.sendCommand(cmd, args...) logCommand(cmd, args, err, conn.database.logging) if err != nil { return nil, err } result, err := conn.resp.receiveResultSet() return result, err }
// Do executes one Redis command and returns // the result as result set. func (ppl *Pipeline) Do(cmd string, args ...interface{}) error { cmd = strings.ToLower(cmd) if strings.Contains(cmd, "subscribe") { return errors.New(ErrUseSubscription, errorMessages) } err := ppl.ensureProtocol() if err != nil { return err } if ppl.database.monitoring { m := monitoring.BeginMeasuring(identifier.Identifier("redis", "command", cmd)) defer m.EndMeasuring() } err = ppl.resp.sendCommand(cmd, args...) logCommand(cmd, args, err, ppl.database.logging) if err != nil { return err } ppl.counter++ return err }
// backendLoop is the backend for the processing of messages. func (c *cell) backendLoop(l loop.Loop) error { totalCellsID := identifier.Identifier("cells", c.env.ID(), "total-cells") monitoring.IncrVariable(totalCellsID) defer monitoring.DecrVariable(totalCellsID) for { select { case <-l.ShallStop(): return c.behavior.Terminate() case event := <-c.eventc: if event == nil { panic("received illegal nil event!") } measuring := monitoring.BeginMeasuring(c.measuringID) err := c.behavior.ProcessEvent(event) measuring.EndMeasuring() if err != nil { logger.Errorf("cell %q processed event %q with error: %v", c.id, event.Topic(), err) return err } } } }
func makeRoomID(name string, buildingName string) string { return identifier.Identifier("room", buildingName, name) }
func makeUserID(name string) string { return identifier.Identifier("user", name) }
func makeBuildingID(name string) string { return identifier.Identifier("building", name) }