Skip to content

Create Timeline struct to hold event chunks from /sync and /messages #230

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 2 commits into from

Conversation

DevinR528
Copy link
Contributor

I'm opening a new PR so I can refer to the old one, this approach of starting with the Timeline struct is different enough it makes sense to me.

We need to keep the Timeline struct around from sync/messages to sync/messages we need it to be complete all the time every time. I'm somewhat assuming that the sled store will be the fallback so if the Timeline doesn't have some info it asks the store?

I added a next_token slice map so BTreeMap<NextBatchToken, SliceIdx>. We needed a way of saying I have an incoming /sync with a prev_batch token get the SliceIdx with the previous next_batch token (basically I see no way of not tracking both tokens, other than linear search every time?).

It's really early but better to know what I'm doing wrong now. A look over the handle_messages_response method would be helpful are my assumptions about missing prev/next_batch tokens right?

May resolve #138

Copy link
Contributor

@poljar poljar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This looks sensible, though it handles only the simple case when we have chunks that neatly connect with our slices. The more complicated case should be quite common, e.g. we have a normal sync, then we have a sync with a limited timeline.

Now the user requests messages from us that include the second sync, the gap and overlaps into the first sync. We'll need a way to store the gap and merge the slices, well ok, merging is probably optional but we'll certainly want to fill the gap neatly.

We can take some inspiration from hydrogen, also we'll need to be mindful of this fact, which is linked from the hydrogen code.

Also the BTreeMap that stores the indexes would need to be size limited for the memory store, while it would need to be a sled Tree in the sled store. I think you were right that this can be used as the Changes equivalent for timelines and we pass that data to the stores when we write stuff.


self.update_events_map_forward(content, last_event_index, next_idx);
} else if self.is_empty() {
let next_idx = SliceIdx(u128::MAX / 2);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's move this into a constructor.

}
}

// TODO: do this in ruma?
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, I think this belongs in Ruma.

let EventIdx(idx) = e;
*idx
})
.unwrap_or_default();
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will default to 0, no? Don't we want to use u128::MAX / 2 here as well?

// like if there is no prev/next_batch token?
}
(None, Some(end)) => {}
(None, None) => todo!("problems"),
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this happens if you have the whole timeline here? You can't move forward nor backwards, though I think Synapse instead sets the tokens to be the same.


self.update_events_map_forward(content, u128::MAX / 2, next_idx);
} else {
todo!("hmmm we got a problem or a gap")
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this means we have a gap? We have a gap if the timeline is marked as limited, so you probably will need to forward that info to this method as well.

// We have the full chunk already
(Some(_), Some(_)) => {}
(Some(_), None) => {
// We have a gap
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is this true? Won't this happen for overlapping stuff as well?
For example

 prev_batch      end               old.start
  |               |                   | 
A - B - C - D - E - F - G - H - I - J - K


self.update_events_map_forward(
// TODO:
// make the methods more general or specific or
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We would probably like to deserialize into some event shim that only contains relevant data, e.g. the event id. Why is this needed here, but not in the backward case?

@DevinR528
Copy link
Contributor Author

DevinR528 commented May 18, 2021

Ok so I think what I'm mostly stuck on is what happens when we have to fix the ordering

0           3          4
|           |          | 
A - B - C - D -  GAP - H - I - J - K

We can't efficiently adjust all the SliceIdx and EventIdx, do we need a more flexible index type? Something like

struct SliceIdx(Vec<u8>); // this would allow us to insert  chunks by pushing 1's

This is a problem right? I didn't realize it was quite so common to get overlapping and segmented chunks that could be shifted about at any time really right?

@poljar
Copy link
Contributor

poljar commented Jun 17, 2021

Ok so I think what I'm mostly stuck on is what happens when we have to fix the ordering

0           3          4
|           |          | 
A - B - C - D -  GAP - H - I - J - K

We can't efficiently adjust all the SliceIdx and EventIdx, do we need a more flexible index type? Something like

struct SliceIdx(Vec<u8>); // this would allow us to insert  chunks by pushing 1's

This is a problem right? I didn't realize it was quite so common to get overlapping and segmented chunks that could be shifted about at any time really right?

Seems that I forgot to answer here, I took a look and it seems that Hydrogen just reorders stuff when it needs to merge overlapping stuff. Wouldn't that work?

@DevinR528
Copy link
Contributor Author

Hydrogen just reorders stuff when it needs to merge overlapping stuff. Wouldn't that work?

Would that mean re-ordering the items in the sled store or somehow keeping track of it and (re)ordering when they are requested?

@poljar
Copy link
Contributor

poljar commented Jun 20, 2021

Hydrogen just reorders stuff when it needs to merge overlapping stuff. Wouldn't that work?

Would that mean re-ordering the items in the sled store or somehow keeping track of it and (re)ordering when they are requested?

I think it means just reordering the slice/event index trees, e.g. events from one slice move into another in a certain order.

@gnunicorn
Copy link
Contributor

Closing in favor of #486 .

@gnunicorn gnunicorn closed this Feb 23, 2022
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Storing timelines in the state store
3 participants