Borked PR: Add get_latest_about_message #7
Reference in New Issue
Block a user
No description provided.
Delete Branch "get-latest-about-message"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
This PR adds a few related things:
As you can see in the above, I was able to take advantage of the serde deserialization via msg.into_ssb_message_content, but then I think to use the fields of a particular variant, you still need to do a match back down into that particular variant... which is actually quite a lot of code compared to, msg.content.get("description"), and would require being written separately for each particular field. I think I prefer the generic get_latest_about_message function making use of Value.get.
One thing I'm curious about, is how we will efficiently get all the fields needed for a profile. In the most inefficient way, we could call functions like this for each of the fields we need. But it would probably be more efficient to do one call to go-sbot get_subset, and then filter that result multiple times in rust, to get all the fields we need. However that could also be built separately and additionally to these individual field-getter functions, which still seem like nice functions to have.
This PR is on top of the previous PR, and is an experiment to see how this feels, but I think its also ready for code review or further thoughts.
next thing I'm going to look into is modifying get_source_until_eof to return an iterator instead of a vector
@notplants
SsbMessageContentTypeenumand associatedis_message_type()method are nice.Interesting to hear that this approach feels more streamlined.
As a general code comment: I've been guilty of this many times in the past but basically any time you see a nested match in your code you should challenge yourself to de-nest. I'll make some relevant code comments on this point.
I'm honestly not sure which path will be more efficient (making many calls to
go-sbotor making one or two big ones and filtering in Rust). I totally agree that the individual field-getter functions are very important to have (the "make Lego blocks first, then build with them" approach).very curious to hear your suggestions about how to denest match statements.
I had also been having an intuition that wasn't the most streamlined way to do things,
but also happy to have a pattern that works for getting things working. Looking forward to learn some new patterns to employ to reduce clutter.
seeing these two code examples makes me wonder if strict typing mostly benefits when your data is actually strictly typed
perhaps when your data is not strictly typed, using a HashMap (or json::Value) is sometimes an easier way to work with it
Coming together nicely!
I've requested a couple changes and offered some feedback on code solutions.
@ -32,0 +36,4 @@Vote,Post,Contact,NoneThis feels like an anti-pattern (having an
Optionas a variant). It's better to wrap theSsbMessageContentTypein anOptionto express "might or might not exist".@ -42,0 +47,4 @@pub fn get_message_type(&self) -> Result<SsbMessageContentType, GolgiError> {let msg_type = self.content.get("type");If our message doesn't have a type then we should return from the function right away.
In this case I'd recommend returning an error (a message without a
typefield incontentis erroneous):This approach simplifies the matching because
msg_typeends up as a&Value. You can then convert the value to&strand match on it straight away.@ -42,0 +50,4 @@.get("type");let enum_type = match msg_type {Some(mtype) => {let mtype_str: &str = mtype.as_str().ok_or(GolgiError::ContentTypeDecode("type field with invalid format".to_string()))?;This error variant is something like
ContentTypeValue("type field value is not a string as expected").@ -42,0 +56,4 @@"post" => SsbMessageContentType::Post,"vote" => SsbMessageContentType::Vote,"contact" => SsbMessageContentType::Contact,_ => return Err(GolgiError::ContentTypeDecode("type field with unknown value".to_string()))I can think of two approaches here to handle the "pattern not matched" case:
Return an error (as you have), but use a different error variant (this error is not the same as "we expected a string but got some other value"). Something like
GolgiError::UnknownContentType.Add a variant to the
SsbMessageContentTypeenumto represent any unknown / unrecognized / unsupported content type:I prefer the second solution since it allows us to represent all valid (ie. string-type) message content types in our
SsbMessageContentTypetype.@ -149,0 +176,4 @@};let kvts: Vec<SsbMessageKVT> = self.get_subset(query).await?;let messages: Vec<SsbMessageValue> = kvts.into_iter().map(|kvt| kvt.value).collect();// TODO: after fixing sbot regression,👍
@ -149,0 +197,4 @@let about_messages = self.get_about_messages(ssb_id).await?;// iterate through the vector looking for an about message with the given key// the first one we find is the most recentfor msg in about_messages {I had some fun playing with a more compact solution (took me a few hours...I'm not great with iterators and transformation yet).
Here's what I came up with:
The nice thing about these iterator methods is being able to avoid nested
matchstatements, especially those that have multiple arms which don't do much (e.g. just returncontinue).nice! the comments on this are great. makes sense. helpful to see flatten used like this too.
having weird gitea issue where when I merged in the PR this PR is based off, it closes the PR...
I think gitea doesn't like when I delete the branch a PR is into, while the PR is still open... even though I was planning on changing the branch to "main" after merging the first one.
I will open a new PR pointing to this one, with the same changes. Workaround for now.
Add get_latest_about_messageto Borked PR: Add get_latest_about_messagePull request closed