aboutsummaryrefslogtreecommitdiff
path: root/cmd
diff options
context:
space:
mode:
authorNeil Alexander <neilalexander@users.noreply.github.com>2020-10-21 15:37:07 +0100
committerGitHub <noreply@github.com>2020-10-21 15:37:07 +0100
commit534f9a9eb69ad35c7492c18c65cdbd55892bf930 (patch)
tree2eb0608e2084fc60599d719ff631ba4a412b1c63 /cmd
parente4f3f38f35ad14a581bed481352a6c1efeb56115 (diff)
Refactor forward extremities (#1556)
* Add resolve-state helper * Tweaks * Refactor forward extremities, again * Tweaks * Minor optimisation * Make path a bit clearer * Only process state/membership if forward extremities have changed * Usage comments in resolve-state
Diffstat (limited to 'cmd')
-rw-r--r--cmd/resolve-state/main.go132
1 files changed, 132 insertions, 0 deletions
diff --git a/cmd/resolve-state/main.go b/cmd/resolve-state/main.go
new file mode 100644
index 00000000..9fb14f05
--- /dev/null
+++ b/cmd/resolve-state/main.go
@@ -0,0 +1,132 @@
+package main
+
+import (
+ "context"
+ "flag"
+ "fmt"
+ "os"
+ "strconv"
+
+ "github.com/matrix-org/dendrite/internal/caching"
+ "github.com/matrix-org/dendrite/internal/setup"
+ "github.com/matrix-org/dendrite/roomserver/state"
+ "github.com/matrix-org/dendrite/roomserver/storage"
+ "github.com/matrix-org/dendrite/roomserver/types"
+ "github.com/matrix-org/gomatrixserverlib"
+)
+
+// This is a utility for inspecting state snapshots and running state resolution
+// against real snapshots in an actual database.
+// It takes one or more state snapshot NIDs as arguments, along with a room version
+// to use for unmarshalling events, and will produce resolved output.
+//
+// Usage: ./resolve-state --roomversion=version snapshot [snapshot ...]
+// e.g. ./resolve-state --roomversion=5 1254 1235 1282
+
+var roomVersion = flag.String("roomversion", "5", "the room version to parse events as")
+
+// nolint:gocyclo
+func main() {
+ ctx := context.Background()
+ cfg := setup.ParseFlags(true)
+ args := os.Args[1:]
+
+ fmt.Println("Room version", *roomVersion)
+
+ snapshotNIDs := []types.StateSnapshotNID{}
+ for _, arg := range args {
+ if i, err := strconv.Atoi(arg); err == nil {
+ snapshotNIDs = append(snapshotNIDs, types.StateSnapshotNID(i))
+ }
+ }
+
+ fmt.Println("Fetching", len(snapshotNIDs), "snapshot NIDs")
+
+ cache, err := caching.NewInMemoryLRUCache(true)
+ if err != nil {
+ panic(err)
+ }
+
+ roomserverDB, err := storage.Open(&cfg.RoomServer.Database, cache)
+ if err != nil {
+ panic(err)
+ }
+
+ blockNIDs, err := roomserverDB.StateBlockNIDs(ctx, snapshotNIDs)
+ if err != nil {
+ panic(err)
+ }
+
+ var stateEntries []types.StateEntryList
+ for _, list := range blockNIDs {
+ entries, err2 := roomserverDB.StateEntries(ctx, list.StateBlockNIDs)
+ if err2 != nil {
+ panic(err2)
+ }
+ stateEntries = append(stateEntries, entries...)
+ }
+
+ var eventNIDs []types.EventNID
+ for _, entry := range stateEntries {
+ for _, e := range entry.StateEntries {
+ eventNIDs = append(eventNIDs, e.EventNID)
+ }
+ }
+
+ fmt.Println("Fetching", len(eventNIDs), "state events")
+ eventEntries, err := roomserverDB.Events(ctx, eventNIDs)
+ if err != nil {
+ panic(err)
+ }
+
+ authEventIDMap := make(map[string]struct{})
+ eventPtrs := make([]*gomatrixserverlib.Event, len(eventEntries))
+ for i := range eventEntries {
+ eventPtrs[i] = &eventEntries[i].Event
+ for _, authEventID := range eventEntries[i].AuthEventIDs() {
+ authEventIDMap[authEventID] = struct{}{}
+ }
+ }
+
+ authEventIDs := make([]string, 0, len(authEventIDMap))
+ for authEventID := range authEventIDMap {
+ authEventIDs = append(authEventIDs, authEventID)
+ }
+
+ fmt.Println("Fetching", len(authEventIDs), "auth events")
+ authEventEntries, err := roomserverDB.EventsFromIDs(ctx, authEventIDs)
+ if err != nil {
+ panic(err)
+ }
+
+ authEventPtrs := make([]*gomatrixserverlib.Event, len(authEventEntries))
+ for i := range authEventEntries {
+ authEventPtrs[i] = &authEventEntries[i].Event
+ }
+
+ events := make([]gomatrixserverlib.Event, len(eventEntries))
+ authEvents := make([]gomatrixserverlib.Event, len(authEventEntries))
+ for i, ptr := range eventPtrs {
+ events[i] = *ptr
+ }
+ for i, ptr := range authEventPtrs {
+ authEvents[i] = *ptr
+ }
+
+ fmt.Println("Resolving state")
+ resolved, err := state.ResolveConflictsAdhoc(
+ gomatrixserverlib.RoomVersion(*roomVersion),
+ events,
+ authEvents,
+ )
+ if err != nil {
+ panic(err)
+ }
+
+ fmt.Println("Resolved state contains", len(resolved), "events")
+ for _, event := range resolved {
+ fmt.Println()
+ fmt.Printf("* %s %s %q\n", event.EventID(), event.Type(), *event.StateKey())
+ fmt.Printf(" %s\n", string(event.Content()))
+ }
+}