Skip to content
This repository has been archived by the owner on Mar 20, 2021. It is now read-only.

Initial implementation of an in-memory version of the API #10

Open
wants to merge 1 commit into
base: master
Choose a base branch
from

Conversation

thomcc
Copy link

@thomcc thomcc commented Oct 25, 2017

This isn't a great API, but it's probably enough to get started with.

Kit, do you mind reviewing?

@thomcc thomcc requested a review from a user October 25, 2017 17:52
@thomcc
Copy link
Author

thomcc commented Oct 25, 2017

This will resolve #3

Copy link

@ghost ghost left a comment

Choose a reason for hiding this comment

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

LGTM, with some comments. @fluffyemily, would you mind reviewing, too? You have a lot more Rust experience, and I think you'd have more insightful feedback here.

pub event: String,
// TODO: Think about more complex types -- Or do we want callers just
// storing JSON here? Can we use std::any::Any and hope to serialize it?
pub data: String
Copy link

Choose a reason for hiding this comment

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

Maybe we can define our own trait for the data, and implement it for strings, numbers, timestamps, and so on? Though, I don't think that will work if we want to call the API from Swift or C++...without more type info, we wouldn't know how to interpret the *c_void that the FFI gives us. Leaving it as a string is fine for now.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, that was my thought too. And since Any exists already, it seems like the trait we might want to use if we were going to go the route of allowing anything.

}

impl PlaceAction {
pub fn new(url: Url, event: &str, data: &str) -> PlaceAction {
Copy link

Choose a reason for hiding this comment

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

We might need to jump through some hoops if we want to expose Url via FFI, but we can work out how to do that later. Just noting it for now.

Copy link
Author

Choose a reason for hiding this comment

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

Yeah, I figured String would honestly not necessarially be any better, given that it's still a complex type (although, I guess it's more likely to be already solved for String than for Url).

Copy link

Choose a reason for hiding this comment

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

@fluffyemily's been looking at how to expose complex types over the FFI.


impl Store for MemoryStore {
fn record_place_action(&mut self, action: PlaceAction) {
if let Some(v) = self.data.get_mut(&action.url) {
Copy link

Choose a reason for hiding this comment

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

I think HashMap::entry exists for cases just like this! 🎉

Copy link
Author

Choose a reason for hiding this comment

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

Noted, I avoided it due to the extra clone it requires (rust-lang/rfcs#1769), but I'm probably overthinking it and that does not matter for Urls.

Copy link

Choose a reason for hiding this comment

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

self.data.insert(action.url.clone(), vec![action]);
}

fn query_place_actions<'a>(&'a self, url: &Url) -> &'a [PlaceAction] {
Copy link

Choose a reason for hiding this comment

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

I wonder if we should return an owned copy of the Vec, instead of tying it to the store's lifetime. On the one hand, that's inefficient; on the other, I wonder how we're going to enforce this in the C++/Swift wrapper. Maybe we can have another layer do the cloning...or maybe this will all work fine as is!

Copy link
Author

Choose a reason for hiding this comment

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

My concern is that it could be an enormous number of records, since we do no filtering. Consider all the actions users might have taken on websites like facebook or reddit.

Given that, I think even returning a slice is bad here. We probably should be returning an iterator of some sort (or a cursor)? But I don't know how we'd do that with FFI either.

Copy link

Choose a reason for hiding this comment

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

Honestly, I wouldn't worry about slices and iterators and cloning and ownership at this stage.

If you're just exploring concepts, you don't need efficiency. If you're not just exploring API modeling concepts, and you're worried about scale, then you don't want a string-based key-value store anyway.

I'd be surprised if a consumer ever had a good reason to call query_place_actions.

You might be interested in how SQLite on Android uses cursor windows.

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants