relations.py 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  1. # -*- coding: utf-8 -*-
  2. # Copyright 2019 New Vector Ltd
  3. #
  4. # Licensed under the Apache License, Version 2.0 (the "License");
  5. # you may not use this file except in compliance with the License.
  6. # You may obtain a copy of the License at
  7. #
  8. # http://www.apache.org/licenses/LICENSE-2.0
  9. #
  10. # Unless required by applicable law or agreed to in writing, software
  11. # distributed under the License is distributed on an "AS IS" BASIS,
  12. # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  13. # See the License for the specific language governing permissions and
  14. # limitations under the License.
  15. import logging
  16. import attr
  17. from synapse.api.errors import SynapseError
  18. logger = logging.getLogger(__name__)
  19. @attr.s(slots=True)
  20. class PaginationChunk:
  21. """Returned by relation pagination APIs.
  22. Attributes:
  23. chunk (list): The rows returned by pagination
  24. next_batch (Any|None): Token to fetch next set of results with, if
  25. None then there are no more results.
  26. prev_batch (Any|None): Token to fetch previous set of results with, if
  27. None then there are no previous results.
  28. """
  29. chunk = attr.ib()
  30. next_batch = attr.ib(default=None)
  31. prev_batch = attr.ib(default=None)
  32. def to_dict(self):
  33. d = {"chunk": self.chunk}
  34. if self.next_batch:
  35. d["next_batch"] = self.next_batch.to_string()
  36. if self.prev_batch:
  37. d["prev_batch"] = self.prev_batch.to_string()
  38. return d
  39. @attr.s(frozen=True, slots=True)
  40. class RelationPaginationToken:
  41. """Pagination token for relation pagination API.
  42. As the results are in topological order, we can use the
  43. `topological_ordering` and `stream_ordering` fields of the events at the
  44. boundaries of the chunk as pagination tokens.
  45. Attributes:
  46. topological (int): The topological ordering of the boundary event
  47. stream (int): The stream ordering of the boundary event.
  48. """
  49. topological = attr.ib()
  50. stream = attr.ib()
  51. @staticmethod
  52. def from_string(string):
  53. try:
  54. t, s = string.split("-")
  55. return RelationPaginationToken(int(t), int(s))
  56. except ValueError:
  57. raise SynapseError(400, "Invalid token")
  58. def to_string(self):
  59. return "%d-%d" % (self.topological, self.stream)
  60. def as_tuple(self):
  61. return attr.astuple(self)
  62. @attr.s(frozen=True, slots=True)
  63. class AggregationPaginationToken:
  64. """Pagination token for relation aggregation pagination API.
  65. As the results are order by count and then MAX(stream_ordering) of the
  66. aggregation groups, we can just use them as our pagination token.
  67. Attributes:
  68. count (int): The count of relations in the boundar group.
  69. stream (int): The MAX stream ordering in the boundary group.
  70. """
  71. count = attr.ib()
  72. stream = attr.ib()
  73. @staticmethod
  74. def from_string(string):
  75. try:
  76. c, s = string.split("-")
  77. return AggregationPaginationToken(int(c), int(s))
  78. except ValueError:
  79. raise SynapseError(400, "Invalid token")
  80. def to_string(self):
  81. return "%d-%d" % (self.count, self.stream)
  82. def as_tuple(self):
  83. return attr.astuple(self)