-
Notifications
You must be signed in to change notification settings - Fork 626
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
Lexicon: embeds in record embeds #691
Conversation
@@ -17,7 +17,7 @@ | |||
"type": "object", | |||
"required": ["uri", "title", "description"], | |||
"properties": { | |||
"uri": {"type": "string", "format": "at-uri"}, | |||
"uri": {"type": "string"}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
i snuck in the uri
format btw 👀
"properties": { | ||
"uri": {"type": "string", "format": "at-uri"}, | ||
"cid": {"type": "string", "format": "cid"}, | ||
"author": {"type": "ref", "ref": "app.bsky.actor.defs#withInfo"}, | ||
"record": {"type": "unknown"} | ||
"record": {"type": "unknown"}, | ||
"embeds": { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
is this an array or just a union?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A single record only has one embed right?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
A post record has at most one embed, but if we want this to remain generic for any record type, I figured there's nothing preventing a record from containing multiple embeds.
If there are multiple, it would be up to the consumer to distinguish them by inspecting
embed.value.record
.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hmmm i think im inclined to make it only one embed 🤔
If you want multiple embeds then you define a new type for that in the union. Similar to how we handle images which is actually up to 4 embeds but represented as only a single embed
This let's us set constraints on how many objects of what type are embedded instead of an unconstrained array
Thoughts?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I guess that also only works if this union is only for schemas that we control. because another developer could take an alternate approach and have some record contain an array of embeds. But I suppose then we could just define a new single embed type that points to that array of embeds. 🤔
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I see what you're getting at 👍 I do think I still lean towards the array but I'm also definitely not married to it. Part of my view on it is treating embeds the same way we might treat any other type: if record embed views needed to present all blobs that appear in the record, for example, I imagine we might end-up with an array of blobs here. That would be necessary to cover cases like profile records which have multiple blobs, i.e. both an avatar and a background banner. I was imagining a similar case where a record could conceivably contain two or more separate embed fields, since there's nothing restricting that.
Here's a case to illustrate where my head was at! Consider a "question and answer" record, where an actor can present a post that poses a question next to a post that answers that question. It might be modeled like this, with an embed for the question post and another for the answer post:
{
"commentary": {"type": "string"},
"questionEmbed": {"type": "ref", "ref": "app.bsky.embed.record"},
"answerEmbed": {"type": "ref", "ref": "app.bsky.embed.record"}
}
At the same time I'd be totally cool saying that we're just not going to cater to that for record embeds, that there's a convention that you should avoid creating records with multiple embed fields 👍 We also do always have the option to go back on the idea of this being a generic record embed, and instead making it specifically a post embed.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The argument would be that the presentation of that possibility would be
"questionAndAnswerEmbedView": {
"questionEmbed": {"type": "ref", "ref": "app.bsky.embed.record"},
"answerEmbed": {"type": "ref", "ref": "app.bsky.embed.record"}
}
And similarly any array of heterogenous embeds can be encapsulated in a lex type that boils it down to a single value that's expressive about what exactly is in the array.
With that being said, it starts to sound a bit overly complex/galaxy brained as a way of encoding what's essentially a list of supplemental "view" data
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think I'd feel more strongly if this was primary data. But since it's supplemental data & the actual structure is imposed by the record, I'm game to leave this field relatively unstructured & just return an array of heterogenous embeds.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Cool cool 👍 it's just a little tricky to deal with view information for any record in a unified way. In the case of a complex record like the question-and-answer one, I would expect a consumer to discover embeds in the original record data. And then fish the view information for those embeds out of this array.
I imagine same might go for blobs if we introduce those here: you discover a blob in the original record, and then fish the view of that blob (e.g. a url to a resized image) out of some collection/array of blob views.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yup yup that checks out. im game with just the array here. thx for the back and forth 🙏
this.embedsForPosts( | ||
records.map((p) => p.uri), | ||
requester, | ||
_depth + 1, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
does this go arbitrarily deep?
so like in the case of a quote post of a quote post of a quote post of an image, this'll return that image?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh wait just saw the _depth > 1 check. so only checks one deep?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Exactly, there's a depth check in two places to ensure embeds are only included two levels deep (i.e. you can receive an embed's embed):
- At the top of the function to ensure it doesn't recurse too deep.
- When mapping to
embeds
in the view. The purpose there is to distinguishembeds
being missing ("embeds are not included" e.g. due to depth) versus empty[]
("embeds are included but there are none").
uri: formatted.uri, | ||
cid: formatted.cid, | ||
author: formatted.author, | ||
record: formatted.record, | ||
embeds: formatted.embed |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is one too many ternaries for my tired saturday brain to handle haha 🙃
I don't quite understand the difference between undefined & the empty array here?
& similar to my prev comment, is there ever a case when the array contains more than one value?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just dropped a couple comments above that will hopefully make it clearer what I was going for. However we land on it, I'll clean this up and drop some comments in the code 👍
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
💎
A few changes to record embeds in here:
#view
rather than#presented
, for consistency.{ $type, value }
, whereas before we had different keys{ $type, record }
,{ $type, external }
, etc. That wasn't necessary since$type
acts as a discriminator for the wrapped value. One small upside there is that the record under a record embed is now(embed.value).record
rather than(embed.record).record
, which feels a little nicer to write.embeds
which can include one or more views of embeds found within the record. If there are multiple, it would be up to the consumer to distinguish them by inspectingembed.value.record
. Embeds are only hydrated one level deep.uri
field was marked as an at-uri, whereas it's actually not limited toat://
(most likely will be a web urihttps://
).Resolves #619