Hello Pact, I am still working on trying to get a...
# pact-plugins
a
Hello Pact, I am still working on trying to get a WebSockets plugin (rust) up and running and are hitting some issues. We have implemented the start_mock_server and stop_mock_server requests and when invoked manually using gRPC and calling the enpoints the WS server starts up and can be interacted with. Calling the Shutdown RPC then closes all connections and returns the match results (of which there are none). We are now trying to implement the consumer test so that it submits the interactions to the server. This is where we are struggling a bit: 1. The pact is being sent to the plugin successfully. The interaction we are setting up is present and looks correct. However when we decode the JSON to a v4 Pact the transport value is always None - does this matter? 2. When running the consumer test the start mock server request is sent and the server is stood up. However the plugin immediately starts shutting down, we get no configure_interaction request and there is a panic on main where the shutdown request was sent but the plugin has already gone away. 3. When we pact_builder.synchronous_messages() in the consumer test the vector is always empty, we therefore cannot loop to perform the tests. Switching to sending the message manually doesn’t fix the problem highlighted in 2. We are trying to follow the pact-plugin-protobuf from the pactflow repo and everything looks the setup the same. But obviously we are missing something here. Is it possible to get some pointers with this? Thanks,
I think I have solved some of this actually. Previously our code looked like this:
Copy code
let mut pact_builder = PactBuilder::new_v4("message-consumer", "message-provider"); // Define the message consumer and provider by name
    let mock_server = pact_builder
        .using_plugin("websockets", None)
        .await
        // Adds an interaction given the message description and type.
        .synchronous_message_interaction("Mallory Message", |mut i| async move {
            /// ...
        })
        .await
        .start_mock_server_async(Some("websockets/transport/websockets"))
        .await;

        pact_builder
            .synchronous_messages()
            .collect::<Vec<SynchronousMessage>>().len() // 0
However if I change it to:
Copy code
let mut pact_builder = PactBuilder::new_v4("message-consumer", "message-provider"); // Define the message consumer and provider by name
    let mut pact_builder_async = pact_builder.using_plugin("websockets", None).await;
    let mock_server = pact_builder_async
        .synchronous_message_interaction("Mallory Message", |mut i| async move {
            // ...
        })
        .await
        .start_mock_server_async(Some("websockets/transport/websockets"))
        .await;

        pact_builder_async
            .synchronous_messages()
            .collect::<Vec<SynchronousMessage>>()
            .len() // 0
Then the interactions vector has 1 element and also the server does not go away and the shutdown method is called and is successful. I guess the original PactBuilder becomes redundant once we do
using_plugin
and get the PactBuilderAsync. The async one then becomes the one we need to work with and keeping the reference to it in stop is what stops the server from shutting down
We still do not get configure_interaction requests though. When should we expect to get thosE?
y
Hey Adam, Thanks for posting up and bravo for jumping in to the world of Pact plugins! I saw in general you have already spoken to a couple of the core maintainers! They are based over in Aus so will catch up with this overnight. Is there a shareable codebase? It would help the maintainers and myself in additional investigations (no worries if not) I'll try my best to answer you questions when I get some free time but feel free to keep posting as you work along, as we will support you as best as we can! We are totally invested in bringing more plugins and plugin authors to the fold :)
u
Oh, that could be a trap for lots of people. I'll need to think of a way to get the first builder to hold the reference to the second one.
a
@Yousaf Nabi (pactflow.io) I’m not sure about shareable codebase. I realise that makes things very difficult but its currently hosted in Comcast Sky’s GitHub org and is private. I’ll have a chat with the powers that be and see what would be best for getting code in front of you guys as its basically impossible to help without looking at the code yourself. I certainly know how that is 😄
Oh, that could be a trap for lots of people. I’ll need to think of a way to get the first builder to hold the reference to the second one.
For the signature of use_plugin could you just do
self
instead of
&self
and move the ownership?
A different question, are
configure_interaction
,
generate_content
and
compare_contents
only relevant if we are adding new Generator and Matcher catalogue entries? We aren’t adding those so do we need to worry much about their implementation. btw, I think the plugin architecture is a brilliant idea and bravo for moving everything to Rust. The tooling is so much more portable and extensible this way and it allows us to get things done as we need to. Great job!
🙏 3
u
A different question, are configure_interaction, generate_content and compare_contents only relevant if we are adding new Generator and Matcher catalogue entries? We aren’t adding those so do we need to worry much about their implementation.
Yes, that is correct. You should be able to just ignore anything you don't need, and if your plugin never provides catalogue entries for those types of things, they will never be called.
👍 1