func WebSensorsAgent(ctx context.Context, db data.DB, u *models.User) { // Get the db's changes, then filter by updates, then // filter by whether this user can read the record changes := data.Filter(data.FilterKind(db.Changes(), models.EventKind), func(c *data.Change) bool { ok, _ := access.CanRead(db, u, c.Record) return ok }) Run: for { select { case c, ok := <-*changes: if !ok { break Run } switch c.Record.(*models.Event).Name { case WEB_SENSOR_LOCATION: webSensorLocation(db, u, c.Record.(*models.Event).Data) } case <-ctx.Done(): break Run } } }
func TaskAgent(ctx context.Context, db data.DB, u *models.User) { changes := data.Filter(data.FilterKind(db.Changes(), models.EventKind), func(c *data.Change) bool { ok, _ := access.CanRead(db, u, c.Record) return ok }) Run: for { select { case c, ok := <-*changes: if !ok { break Run } switch c.Record.(*models.Event).Name { case TaskMakeGoal: taskMakeGoal(db, u, c.Record.(*models.Event).Data) case TaskDropGoal: taskDropGoal(db, u, c.Record.(*models.Event).Data) } case <-ctx.Done(): break Run } } }
func TestLocationAgent(t *testing.T) { db := mem.NewDB() u, _, err := user.Create(db, "username", "password") if err != nil { t.Fatal(err) } changes := data.FilterKind(db.Changes(), models.ProfileKind) ctx, stop := context.WithCancel(context.Background()) go agents.LocationAgent(ctx, db, u) defer stop() // give control to agent thread time.Sleep(1 * time.Millisecond) _, loc, err := event.LocationUpdate(db, u, 50, 50, 50) if err != nil { t.Fatal(err) } select { case profileChange := <-*changes: p := profileChange.Record.(*models.Profile) if loc.Id != p.LocationId { t.Fatal("Expected profile's location id to now match be the new location ") } case <-time.After(100 * time.Millisecond): t.Fatal("Timed out waiting for profile update") } }
func TestWebSensorsAgent(t *testing.T) { db := mem.NewDB() u, _, err := user.Create(db, "username", "password") if err != nil { t.Fatal(err) } changes := data.FilterKind(db.Changes(), models.EventKind) ctx, stop := context.WithCancel(context.Background()) go agents.WebSensorsAgent(ctx, db, u) defer stop() // give control to agent thread time.Sleep(1 * time.Millisecond) _, err = event.WebSensorLocation(db, u, 50, 50) if err != nil { t.Fatal(err) } // read off the event we just created <-*changes select { case eventChange := <-*changes: e := eventChange.Record.(*models.Event) if e.Name != "Location Update" { t.Fatal("Expected a location update to be produced") } case <-time.After(100 * time.Millisecond): t.Fatal("Timed out waiting for event creation") } }
func LocationAgent(ctx context.Context, db data.DB, u *models.User) { locTag, err := tag.ForName(db, u, tag.Location) if err != nil { log.Fatal(err) } updTag, err := tag.ForName(db, u, tag.Update) if err != nil { log.Fatal(err) } // Get the db's changes, then filter by updates, then // filter by whether this user can read the record changes := data.Filter(data.FilterKind(db.Changes(), models.EventKind), func(c *data.Change) bool { ok, _ := access.CanRead(db, u, c.Record) if !ok { return false } return event.ContainsTags(c.Record.(*models.Event), locTag, updTag) }) Run: for { select { case c, ok := <-*changes: if !ok { break Run } locationUpdate(db, u, c.Record.(*models.Event)) case <-ctx.Done(): break Run } } }
func RecordChangesGET(ctx context.Context, ws *websocket.Conn, db data.DB, logger services.Logger) { l := logger.WithPrefix("RecordChangesGet: ") u, ok := user.FromContext(ctx) if !ok { l.Print("failed to retrieve user from context") return } // Get the db's changes, then filter by updates, then // filter by whether this user can read the record changes := data.Filter(db.Changes(), func(c *data.Change) bool { ok, err := access.CanRead(db, u, c.Record) if err != nil { l.Printf("error checking access control: %s", err) } return ok }) var kind data.Kind if kindParam := ws.Request().Form.Get(kindParam); kindParam != "" { kind = data.Kind(kindParam) if _, ok := models.Kinds[kind]; !ok { l.Printf("unrecognized kind: %q", kind) if err := websocket.Message.Send(ws, fmt.Sprintf("The kind %q is not recognized", kind)); err != nil { if err != io.EOF { l.Printf("error sending on websocket: %s", err) } } return } // If a kind was specified, filter by it changes = data.FilterKind(changes, kind) } for { select { case change, ok := <-*changes: if !ok { l.Printf("change channel was closed") return } l.Printf("recieved change: %+v", change) changeTransport := transfer.Change(change) if err := websocket.JSON.Send(ws, changeTransport); err != nil { if err != io.EOF { l.Printf("error sending to socket: %s", err) } return } case <-time.After(5 * time.Second): l.Printf("no change in 5 seconds, but still listening") case <-ctx.Done(): l.Printf("context cancelled") // context was cancelled return } } }