Beispiel #1
0
func (s syncService) FullSync(user ct.UserId, limit uint) (*types.InitialSync, types.Error) {
	maxMessage := s.messageSource.Max()
	maxPresence := s.presenceSource.Max()
	maxTyping := s.typingSource.Max()

	userSet, err := s.membershipStore.Peers(user)
	if err != nil {
		return nil, err
	}
	indexedPresences, err := s.presenceSource.Range(&user, userSet, nil, 0, maxPresence, limit)
	if err != nil {
		return nil, err
	}
	presences := indexedToEvents(indexedPresences)

	rooms, err := s.membershipStore.Rooms(user)
	summaries := make([]types.RoomSummary, len(rooms))
	if err != nil {
		return nil, err
	}
	end := types.NewStreamToken(maxMessage, maxPresence, maxTyping)

	for i, room := range rooms {
		if err := s.roomSummary(&summaries[i], user, room, end, limit); err != nil {
			return nil, err
		}
	}

	initialSync := types.InitialSync{end, presences, summaries}

	return &initialSync, nil
}
Beispiel #2
0
func (s syncService) RoomSync(user ct.UserId, room ct.RoomId, limit uint) (*types.RoomInitialSync, types.Error) {
	maxMessage := s.messageSource.Max()
	maxPresence := s.presenceSource.Max()
	maxTyping := s.typingSource.Max()

	userSet := map[ct.UserId]struct{}{}
	users, err := s.membershipStore.Users(room)
	if err != nil {
		return nil, err
	}
	for _, user := range users {
		userSet[user] = struct{}{}
	}

	indexedPresences, err := s.presenceSource.Range(&user, userSet, nil, 0, maxPresence, limit)
	if err != nil {
		return nil, err
	}
	presences := indexedToEvents(indexedPresences)

	sync := types.RoomInitialSync{
		Presence: presences,
	}

	end := types.NewStreamToken(maxMessage, maxPresence, maxTyping)
	if err := s.roomSummary(&sync.RoomSummary, user, room, end, limit); err != nil {
		return nil, err
	}
	return &sync, nil
}
Beispiel #3
0
func (e roomsEndpoint) getMessages(req *http.Request, params httprouter.Params) interface{} {
	room, user, err := e.getRoomAndUser(req, params)
	if err != nil {
		return err
	}

	var from *types.StreamToken
	var to *types.StreamToken

	query := req.URL.Query()
	fromStr := query.Get("from")
	toStr := query.Get("to")
	dir := query.Get("dir")
	limitStr := query.Get("limit")

	if fromStr != "" {
		token, err := types.ParseStreamToken(fromStr)
		if err != nil {
			return types.BadQueryError(err.Error())
		}
		from = &token
	}

	if toStr != "" {
		token, err := types.ParseStreamToken(toStr)
		if err != nil {
			return types.BadQueryError(err.Error())
		}
		to = &token
	}

	if dir == "b" {
		token := types.NewStreamToken(0, 0, 0)
		to = &token
	}

	var limit uint64

	var parseErr error
	if limitStr == "" {
		limit = 10 //TODO: make configurable
	} else {
		limit, parseErr = strconv.ParseUint(limitStr, 10, 32)
		if parseErr != nil {
			return types.BadQueryError(parseErr.Error())
		}
		if limit > 100 {
			limit = 100 //TODO: make configurable
		}
	}
	eventRange, err := e.eventService.Messages(user, room, from, to, uint(limit))
	log.Println("TO", to, eventRange)
	if err != nil {
		return err
	}

	return eventRange
}
Beispiel #4
0
func (e eventsEndpoint) getEvents(req *http.Request) interface{} {
	authedUser, err := readAccessToken(e.userService, e.tokenService, req)
	if err != nil {
		return err
	}

	query := urlQuery{req.URL.Query()}

	from, err := query.parseStreamToken("from")
	if err != nil {
		return err
	}

	to, err := query.parseStreamToken("to")
	if err != nil {
		return err
	}

	limit, err := query.parseUint("limit", 10)
	if err != nil {
		return err
	}
	if limit > 100 {
		limit = 100 //TODO: make configurable
	}

	timeout, err := query.parseUint("timeout", 5000)
	if err != nil {
		return err
	}
	if timeout > 60000 {
		timeout = 60000 //TODO: make configurable
	}
	if timeout < 100 {
		timeout = 100
	}

	dir := query.Get("dir")
	if dir == "b" {
		token := types.NewStreamToken(0, 0, 0)
		to = &token
	}

	cancel := make(chan struct{})

	go func(timeout time.Duration) {
		time.Sleep(timeout)
		close(cancel)
	}(time.Millisecond * time.Duration(timeout))

	chunk, err := e.eventService.Range(authedUser, from, to, uint(limit), cancel)
	if err != nil {
		return err
	}

	return chunk
}
Beispiel #5
0
func (s syncService) roomSummary(
	summary *types.RoomSummary,
	user ct.UserId,
	room ct.RoomId,
	end types.StreamToken,
	limit uint,
) types.Error {
	roomSet := map[ct.RoomId]struct{}{
		room: struct{}{},
	}
	messages, err := s.messageSource.Range(nil, nil, roomSet, end.MessageIndex, 0, limit)
	if err != nil {
		return err
	}
	startIndex := end.MessageIndex
	if len(messages) > 0 {
		startIndex = messages[0].Index()
	}
	start := types.NewStreamToken(startIndex, end.PresenceIndex, end.TypingIndex)
	eventRange := types.NewEventStreamRange(indexedToEvents(messages), start, end)
	states, err := s.rooms.EntireRoomState(room)
	if err != nil {
		return err
	}
	membershipState, err := s.rooms.RoomState(room, types.EventTypeMembership, user.String())
	if err != nil {
		return err
	}
	membership := membershipState.Content.(*types.MembershipEventContent).Membership
	joinRuleState, err := s.rooms.RoomState(room, types.EventTypeJoinRules, "")
	if err != nil {
		return err
	}
	joinRule := joinRuleState.Content.(*types.JoinRulesEventContent).JoinRule
	visibility := joinRule.ToVisibility()
	summary.Membership = membership
	summary.RoomId = room
	summary.Messages = eventRange
	summary.State = states
	summary.Visibility = visibility
	return nil
}
Beispiel #6
0
func (s eventService) Range(
	user ct.UserId,
	from, to *types.StreamToken,
	limit uint,
	cancel chan struct{},
) (chunk *types.EventStreamRange, err types.Error) {
	var eventCh chan ct.IndexedEvent

	if from == nil || to == nil || from.MessageIndex > to.MessageIndex {
		eventCh, err = s.asyncEventSource.Listen(user, cancel)
		if err != nil {
			return nil, err
		}
	}

	maxMessage := s.messageSource.Max()
	maxPresence := s.presenceSource.Max()
	maxTyping := s.typingSource.Max()

	var fromMessage uint64
	var fromPresence uint64
	var fromTyping uint64

	if from != nil {
		fromMessage = from.MessageIndex
		if fromMessage > maxMessage {
			fromMessage = maxMessage
		}
		fromPresence = from.PresenceIndex
		if fromPresence > maxPresence {
			fromPresence = maxPresence
		}
		fromTyping = from.TypingIndex
		if fromTyping > maxTyping {
			fromTyping = maxTyping
		}
	} else {
		fromMessage = maxMessage
		fromPresence = maxPresence
		fromTyping = maxTyping
	}

	var toMessage uint64
	var toPresence uint64
	var toTyping uint64

	if to != nil {
		toMessage = to.MessageIndex
		toPresence = to.PresenceIndex
		toTyping = to.TypingIndex
	} else {
		toMessage = maxMessage
		toPresence = maxPresence
		toTyping = maxTyping
	}

	userSet, err := s.membershipStore.Peers(user)
	if err != nil {
		return nil, err
	}

	roomSet := map[ct.RoomId]struct{}{}
	rooms, err := s.membershipStore.Rooms(user)
	if err != nil {
		return nil, err
	}
	for _, room := range rooms {
		roomSet[room] = struct{}{}
	}

	messages, err := s.messageSource.Range(&user, userSet, roomSet, fromMessage, toMessage, limit)
	if err != nil {
		return nil, err
	}
	presences, err := s.presenceSource.Range(&user, userSet, roomSet, fromPresence, toPresence, limit)
	if err != nil {
		return nil, err
	}
	typings, err := s.typingSource.Range(&user, userSet, roomSet, fromTyping, toTyping, limit)
	if err != nil {
		return nil, err
	}

	log.Printf("getting events from %d to %d, max %d, %#v", fromMessage, toMessage, maxMessage, eventCh)

	if eventCh != nil {
		blocking := true
		if to != nil && toMessage <= maxMessage && toPresence <= maxPresence && toTyping <= maxTyping {
			blocking = false
		}

		gotEvent := false
		var event ct.IndexedEvent
		if blocking && len(messages)+len(presences)+len(typings) == 0 {
			event, gotEvent = <-eventCh
		} else {
			select {
			case event, gotEvent = <-eventCh:
			default:
			}
		}
		log.Printf("async event: %#v blocking: %#v len: %#v", event, blocking, len(messages)+len(presences)+len(typings))

		if gotEvent && uint(len(messages)) < limit {
			eventType := event.Event().GetEventType()
			if eventType == types.EventTypePresence {
				if len(presences) == 0 || presences[len(presences)-1].Index() < event.Index() {
					if to == nil || event.Index() < toPresence {
						presences = append(presences, event)
					}
				}
			} else if eventType == types.EventTypeTyping {
				if len(typings) == 0 || typings[len(typings)-1].Index() < event.Index() {
					if to == nil || event.Index() < toTyping {
						typings = append(typings, event)
					}
				}
			} else {
				if len(messages) == 0 || messages[len(messages)-1].Index() < event.Index() {
					if to == nil || event.Index() < toMessage {
						messages = append(messages, event)
					}
				}
			}
		}
	}

	messageIndex := fromMessage
	presenceIndex := fromPresence
	typingIndex := fromTyping

	if len(messages) > 0 {
		messageIndex = messages[len(messages)-1].Index() + 1
	}
	if len(presences) > 0 {
		presenceIndex = presences[len(presences)-1].Index() + 1
	}
	if len(typings) > 0 {
		typingIndex = typings[len(typings)-1].Index() + 1
	}

	start := types.NewStreamToken(fromMessage, fromPresence, fromTyping)
	end := types.NewStreamToken(messageIndex, presenceIndex, typingIndex)

	events := make([]ct.Event, len(messages)+len(presences)+len(typings))

	for i, _ := range events {
		if i < len(messages) {
			events[i] = messages[i].Event()
		} else {
			i -= len(messages)
			if i < len(presences) {
				events[len(messages)+i] = presences[i].Event()
			} else {
				i -= len(presences)
				events[len(messages)+len(presences)+i] = typings[i].Event()
			}
		}
	}
	log.Printf("got events from %d to %d: %#v", fromMessage, messageIndex, events)

	chunk = types.NewEventStreamRange(events, start, end)

	return chunk, nil

	//	ch = eventMux.listen(user)
	//	to = eventBuffer.max // atomic

	//	resultChan = make(chan, limit)

	//	result = []
	//	found = 0
	//	event = indices[from]

	//	while found < limit && event.index < to:
	//		event = event.next
	//		if filter.test(user, event):
	//			resultChan <- event
	//			found += 1

	//	if found < limit {
	//		switch {
	//		new <- ch
	//			if new.index > to:

	//		default:
	//		}
	//		new = readAll(ch)

	//	}
}
Beispiel #7
0
func (s eventService) Messages(
	user ct.UserId,
	room ct.RoomId,
	from, to *types.StreamToken,
	limit uint,
) (eventRange *types.EventStreamRange, err types.Error) {
	maxMessage := s.messageSource.Max()

	var fromMessage uint64
	var presenceIndex uint64
	var typingIndex uint64

	if from != nil {
		fromMessage = from.MessageIndex
		presenceIndex = from.PresenceIndex
		typingIndex = from.TypingIndex
		if fromMessage > maxMessage {
			fromMessage = maxMessage
		}
	} else {
		fromMessage = maxMessage
		presenceIndex = s.presenceSource.Max()
		typingIndex = s.typingSource.Max()
	}

	var toMessage uint64

	if to != nil {
		toMessage = to.MessageIndex
	} else {
		toMessage = maxMessage
	}
	log.Println("to message", toMessage, to)

	roomSet := map[ct.RoomId]struct{}{
		room: struct{}{},
	}

	messages, err := s.messageSource.Range(nil, nil, roomSet, fromMessage, toMessage, limit)
	if err != nil {
		return nil, err
	}

	log.Printf("getting messages from %d to %d, max %d", fromMessage, toMessage, maxMessage)

	messagesStart := fromMessage
	messagesEnd := fromMessage

	if len(messages) > 0 {
		messagesStart = messages[0].Index()
		messagesEnd = messages[len(messages)-1].Index() + 1
	}

	if to != nil && to.MessageIndex < fromMessage {
		messagesEnd, messagesStart = messagesStart, messagesEnd
	}

	start := types.NewStreamToken(messagesStart, presenceIndex, typingIndex)
	end := types.NewStreamToken(messagesEnd, presenceIndex, typingIndex)

	events := make([]ct.Event, len(messages))

	for i, _ := range events {
		events[i] = messages[i].Event()
	}
	log.Printf("got messages from %d to %d: %#v", messagesStart, messagesEnd, events)

	eventRange = types.NewEventStreamRange(events, start, end)

	return eventRange, nil
}