def GetHostRequest(self, request, context): with session_scope() as session: host_request = (session.query(HostRequest).filter( HostRequest.conversation_id == request.host_request_id).filter( or_(HostRequest.from_user_id == context.user_id, HostRequest.to_user_id == context.user_id)).one_or_none()) if not host_request: context.abort(grpc.StatusCode.NOT_FOUND, errors.HOST_REQUEST_NOT_FOUND) initial_message = (session.query( Message.time).filter(Message.conversation_id == host_request.conversation_id).order_by( Message.id.asc()).limit(1).one()) latest_message = (session.query(Message).filter( Message.conversation_id == host_request.conversation_id).order_by( Message.id.desc()).limit(1).one()) return requests_pb2.HostRequest( host_request_id=host_request.conversation_id, from_user_id=host_request.from_user_id, to_user_id=host_request.to_user_id, status=hostrequeststatus2api[host_request.status], created=Timestamp_from_datetime(initial_message.time), from_date=date_to_api(host_request.from_date), to_date=date_to_api(host_request.to_date), last_seen_message_id=host_request.from_last_seen_message_id if context.user_id == host_request.from_user_id else host_request.to_last_seen_message_id, latest_message=message_to_pb(latest_message), )
def ListHostRequests(self, request, context): if request.only_sent and request.only_received: context.abort(grpc.StatusCode.INVALID_ARGUMENT, errors.HOST_REQUEST_SENT_OR_RECEIVED) with session_scope() as session: pagination = request.number if request.number > 0 else DEFAULT_PAGINATION_LENGTH pagination = min(pagination, MAX_PAGE_SIZE) # By outer joining messages on itself where the second id is bigger, only the highest IDs will have # none as message_2.id. So just filter for these ones to get highest messages only. # See https://stackoverflow.com/a/27802817/6115336 message_2 = aliased(Message) query = (session.query( Message, HostRequest, Conversation).outerjoin( message_2, and_(Message.conversation_id == message_2.conversation_id, Message.id < message_2.id)).join( HostRequest, HostRequest.conversation_id == Message.conversation_id).join( Conversation, Conversation.id == HostRequest.conversation_id).filter( message_2.id == None).filter( or_( HostRequest.conversation_id < request.last_request_id, request.last_request_id == 0))) if request.only_sent: query = query.filter( HostRequest.from_user_id == context.user_id) elif request.only_received: query = query.filter(HostRequest.to_user_id == context.user_id) else: query = query.filter( or_(HostRequest.to_user_id == context.user_id, HostRequest.from_user_id == context.user_id)) # TODO: I considered having the latest control message be the single source of truth for # the HostRequest.status, but decided agains it because of this filter. # Another possibility is to filter in the python instead of SQL, but that's slower if request.only_active: query = query.filter( or_( HostRequest.status == HostRequestStatus.pending, HostRequest.status == HostRequestStatus.accepted, HostRequest.status == HostRequestStatus.confirmed, )) query = query.filter(HostRequest.end_time <= func.now()) query = query.order_by(Message.id.desc()).limit(pagination + 1) results = query.all() host_requests = [ requests_pb2.HostRequest( host_request_id=result.HostRequest.conversation_id, from_user_id=result.HostRequest.from_user_id, to_user_id=result.HostRequest.to_user_id, status=hostrequeststatus2api[result.HostRequest.status], created=Timestamp_from_datetime( result.Conversation.created), from_date=date_to_api(result.HostRequest.from_date), to_date=date_to_api(result.HostRequest.to_date), last_seen_message_id=result.HostRequest. from_last_seen_message_id if context.user_id == result.HostRequest.from_user_id else result.HostRequest.to_last_seen_message_id, latest_message=message_to_pb(result.Message), ) for result in results[:pagination] ] last_request_id = (min( map( lambda g: g.HostRequest.conversation_id if g.HostRequest else 1, results[:pagination])) if len(results) > 0 else 0) # TODO no_more = len(results) <= pagination return requests_pb2.ListHostRequestsRes( last_request_id=last_request_id, no_more=no_more, host_requests=host_requests)