-
Notifications
You must be signed in to change notification settings - Fork 83
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
Refactor/messages crate #754
Conversation
f2d0ee1
to
63cbc90
Compare
Codecov Report
@@ Coverage Diff @@
## main #754 +/- ##
=======================================
Coverage 54.66% 54.67%
=======================================
Files 381 381
Lines 36858 36864 +6
Branches 8123 8101 -22
=======================================
+ Hits 20150 20154 +4
- Misses 10706 10711 +5
+ Partials 6002 5999 -3
Flags with carried forward coverage won't be shown. Click here to find out more. see 7 files with indirect coverage changes Help us with your feedback. Take ten seconds to tell us how you rate us. Have a feature suggestion? Share it here. |
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.
Barely went through everything but went through a little bit. Produced this small PR in the process
#755
I'd suggest to take a look at some instance where breaking change protocol actually happened, like https://github.com/hyperledger/aries-rfcs/blob/main/features/0454-present-proof-v2/README.md |
In PR #755 I added some tests, how would I go about it in the opposite direction on Message Family level. Eg something like this
Obviously I need to implement |
To accommodate this in the future, we would expand the Then create the "end messages" (e.g.: PresentProofV2_0), implement |
While using the I took the liberty of introducing I also adjusted your tests to rather use |
a763e64
to
cbba7b4
Compare
71b7d74
to
02438e3
Compare
So, in the view of handling some common patterns that either already occur or should/will be occurring through the codebase, I gave some thought to how to approach messages in a more pragmatic way. The ProblemPrimarily, messages and their decorators seem to be too intertwined which makes processing cumbersome, error-prone and not very contained. If we think about threading, for example, it is pretty hard to come up with a way of replying to a message or starting a subthread in a consistent manner, irrespective of the message. Some messages need a Extracting the thread out of the data structure is one problem. There's also the need to extract the Proposed SolutionAfter some thinking and quite a few complex and ocult ideas, I came up with the following (reasonable, if you ask me) approach: // NoDataNoProblem is a type which ignores any serialized (or absent) value and serializes to nothing.
// Flattening nothing results in more nothing, so it's completely invisible when serialized.
#[derive(Serialize, Deserialize, Debug)]
pub struct Message<C, MD, FD = NoDataNoProblem>
{
#[serde(rename = "@id")]
id: String,
#[serde(flatten)]
content: C,
#[serde(flatten)]
msg_decorators: MD,
#[serde(flatten)]
field_decorators: FD,
} What?From a serialization/deserialization perspective, this structure has the same output/input as the current messages. The benefit is that by flattening the data into parts, we can destructure this type and do different things with it in different parts of the code. /// Current Request type
#[derive(Clone, Debug, Deserialize, Serialize)]
pub struct Request {
#[serde(rename = "@id")]
pub id: String,
pub label: String,
pub connection: ConnectionData,
#[serde(skip_serializing_if = "Option::is_none")]
#[serde(rename = "~thread")]
pub thread: Option<Thread>,
#[serde(rename = "~timing")]
#[serde(skip_serializing_if = "Option::is_none")]
pub timing: Option<Timing>,
}
/// New Request type after monomorphization:
#[derive(Serialize, Deserialize, Debug)]
pub struct Message
{
#[serde(rename = "@id")]
id: String,
#[serde(flatten)]
content: RequestContent,
#[serde(flatten)]
msg_decorators: RequestMsgDecorators,
#[serde(flatten)]
field_decorators: NoDataNoProblem,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RequestMsgDecorators {
#[serde(rename = "~thread")]
pub thread: Option<Thread>,
#[serde(rename = "~timing")]
pub timing: Option<Timing>,
}
#[derive(Serialize, Deserialize, Debug)]
pub struct RequestContent {
pub label: String,
pub connection: ConnectionData,
} It's probably clearer now that destructuring In the threading case, we can easily get our hands on the underlying Also, there's nothing preventing the protocol state machines to accept some other things rather than just FD (Field Decorators)Not meaning to hate but I personally find this field decorator thing to be one of the worst designs in software development of this scale. I assume that the whole point of decorators is to have a set of fields independent of a protocol, and that's actually good. I however do not see a reason why field decorators could not be transformed/incorporated into messsage decorators so you have a singular data structure serving a certain purpose rather than stuff spread all across the JSON ¯\(ツ)/¯. In any case, when it comes to message processing, some field decorators are instrumental to the message and are practically part of it. These would not be defined here, but rather in the However, stuff like By default, the So what's next?I'll get to refactoring messages to use this pattern. There's still some experimentation I need/want to do before that, especially in terms of how the messages get segregated based on their @Patrik-Stas, @mirgee We had the chance to talk a bit about this already, but still feel free to comment here any ideas/observations you might have. @gmulhearn, what do you think about this? |
Combine MD and FDGiven the community call discussion, it seems like a good idea to actually combine the message decorators and field decorators into a structure defined for each message. The whole point is to destructure it anyway, so that's most likely fine. Our goal is to mainly keep the protocol state machine relevant data separate from the protocol state machine agnostic data, so we can process them independently. Field Decorators in nested JSONPer the RFC, a field decorator is used as a sibling to the field it decorates. So they technically can be found at lower levels of the JSON. I don't know of any actual implementations of something like that (apart from nested messages as with the OOB connectionless stuff, but that's handled as a contained message). If, however, something like that surfaces, I think we can easily accommodate it to the same message structure that we have, with the caveat of doing some conversions through some intermediary types to normalize the data. |
Finally, the |
af42ba4
to
707d1a8
Compare
ec890f1
to
162acb6
Compare
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.
Good job! The
Message<Content, Decorator>
and the related traits, the MessageWithKind
blanket impl etc. seem to play pretty well together.
Just please remove reformatting changes applied across the board in unrelated crates. (it also makes github really slow, making it bit more difficult to review, as there's many modified files)
Some of the unfinished pieces which are not too critical good be very good first issues for newcomers! Leave them something! :-) This is good and well organized code to learn from. I left suggestions to do this with some of my review comments.
d4d4235
to
4b317bc
Compare
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
…crate) Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
f04bbf9
to
196c1d4
Compare
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.
Great job, left a few minors comments but green light from me 🟢
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 minor nitpicks otherwise LGTM 👍
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
…ybeKnown Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com>
* Implement messages2 crate as pending replacement for messages Signed-off-by: Bogdan Mircea <mirceapetrebogdan@gmail.com> Signed-off-by: Andy Waine <88730354+Andy-Waine@users.noreply.github.com>
Refactor of messages crate.
Planned steps:
messages2
.messages2
crate will be merged and we can start using it inaries-vcx
, slowly replacing the old crate.messages
crate are addressed, it will be removed.Pending tasks:
Module structure:
Move theerror
module insidemessage_type
as these are the only custom errors that can arisecrate::msg_types::types::traits
tocrate::msg_types::traits
.crate::protocols
to separate the message implementations from the traits.Service
fromcrate::protocols::common
tocrate::protocols::out_of_band
, as it's only used there.composite_message
moduleHasKind
trait out ofdelayed_serde
moduleMSG_TYPE
contant toutils
misc
module that contains stuff such asMimeType
, theNothing
type, and theutils
module.Documentation:
crate::msg_types::traits
module contents.MessageType
MsgWithType
Message
and the way it composes/decomposesHasKind
MessageWithKind
traitregistry
moduleActor
Role
enumProtocol
(formerlyMessageFamily
) typeTesting:
Test serialization equality between old messages and new messages (to be placed in the old messages crate)MaybeKnown
serialization/deserialization toKnown
andUnknown
.Renames:
Type
in their name to avoid collisions.crate::msg_types::types
module - renamed tocrate::msg_types::protocols
.crate::protocols::nameless
module - renamed tocrate::msg_fields::protocols
.crate::message::Message
to avoid confusion withAriesMessage
- renamed toMsgParts
.Nothing
- renamed toNoDecorators
.MajorVersion
trait - renamed toProtocolVersion
.HasKind
trait - renamed toMessageWithKind
ConcreteMessage
trait - renamed toMessageContent
Kind
suffix. E.g:OutOfBandV1_1Kind
toOutOfBandV1_1
Actor
toRole
MessageFamily
orfamily
toProtocol
orprotocol_name
This list is not exhaustive. Ideally, as progress is made or ideas are proposed, specific items would be added to it, such as:
This
toOther
Something
Any help in identifying, adding or even implementing items on this list is much appreciated. Reviewing the PR should result in ideas of what would be needed.
In terms of documentation, if it's not easily understandable in a short time (10-15 seconds) what a piece of code does and how, then that's a good sign that comments would be needed. I personally prefer exhaustive comments in favor of little/no comments.
Proposing items can be done by commenting on this PR or reaching out directly. I will then add them to the list. There's no bad idea of things that should be documented/renamed/tested/etc., so don't be shy.