mirror of
https://git.anonymousland.org/anonymousland/synapse-product.git
synced 2025-05-17 05:42:58 -04:00
Use a chain cover index to efficiently calculate auth chain difference (#8868)
This commit is contained in:
parent
671138f658
commit
1315a2e8be
14 changed files with 1777 additions and 56 deletions
|
@ -13,8 +13,21 @@
|
|||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
import heapq
|
||||
from itertools import islice
|
||||
from typing import Iterable, Iterator, Sequence, Tuple, TypeVar
|
||||
from typing import (
|
||||
Dict,
|
||||
Generator,
|
||||
Iterable,
|
||||
Iterator,
|
||||
Mapping,
|
||||
Sequence,
|
||||
Set,
|
||||
Tuple,
|
||||
TypeVar,
|
||||
)
|
||||
|
||||
from synapse.types import Collection
|
||||
|
||||
T = TypeVar("T")
|
||||
|
||||
|
@ -46,3 +59,41 @@ def chunk_seq(iseq: ISeq, maxlen: int) -> Iterable[ISeq]:
|
|||
If the input is empty, no chunks are returned.
|
||||
"""
|
||||
return (iseq[i : i + maxlen] for i in range(0, len(iseq), maxlen))
|
||||
|
||||
|
||||
def sorted_topologically(
|
||||
nodes: Iterable[T], graph: Mapping[T, Collection[T]],
|
||||
) -> Generator[T, None, None]:
|
||||
"""Given a set of nodes and a graph, yield the nodes in toplogical order.
|
||||
|
||||
For example `sorted_topologically([1, 2], {1: [2]})` will yield `2, 1`.
|
||||
"""
|
||||
|
||||
# This is implemented by Kahn's algorithm.
|
||||
|
||||
degree_map = {node: 0 for node in nodes}
|
||||
reverse_graph = {} # type: Dict[T, Set[T]]
|
||||
|
||||
for node, edges in graph.items():
|
||||
if node not in degree_map:
|
||||
continue
|
||||
|
||||
for edge in edges:
|
||||
if edge in degree_map:
|
||||
degree_map[node] += 1
|
||||
|
||||
reverse_graph.setdefault(edge, set()).add(node)
|
||||
reverse_graph.setdefault(node, set())
|
||||
|
||||
zero_degree = [node for node, degree in degree_map.items() if degree == 0]
|
||||
heapq.heapify(zero_degree)
|
||||
|
||||
while zero_degree:
|
||||
node = heapq.heappop(zero_degree)
|
||||
yield node
|
||||
|
||||
for edge in reverse_graph[node]:
|
||||
if edge in degree_map:
|
||||
degree_map[edge] -= 1
|
||||
if degree_map[edge] == 0:
|
||||
heapq.heappush(zero_degree, edge)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue