Skip to content
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

Could it be possible to stream line the boiler plate code? #6

Open
avnerbarr opened this issue Feb 14, 2024 · 1 comment
Open

Could it be possible to stream line the boiler plate code? #6

avnerbarr opened this issue Feb 14, 2024 · 1 comment

Comments

@avnerbarr
Copy link

Hey Charles,

I starred the repo. It seems to bridge an annoying usability gap in the XPC framework,

What I have noticed is that there is a lot of boiler plate code when you have calls to remote functions that need to receive multiple parameters as well as callback functions to stream data.

In your example you have a "Long running function".

I have a similar case and needed to go through the hoops of creating listeners on the caller end and creating a data class to hold the multiple parameters to pass to the RPC call as well as the callback stream.

For example here:

// the callback side
let listener = try XPCListener(type: .anonymous, codeSigningRequirement: nil)
// Does name matter?

        // would be nice if we could call the functions as if they were plain methods . Actors?
        listener.setMessageHandler(name: "blah") { (_, value: SomeDecodableType) in
            print(value)
        }
        listener.errorHandler = { a, b in
            print(a,b)
        }
        let request = SomeCodableArgumentToPass(callback: listener.endpoint, .... all the parameters to pass along to the RPC....)
        listener.activate()
        try await service.sendMessage(name: "messageNameOnTheServerSide", request: request)



// the server side:

let serviceListener = try! XPCListener(type: .service, codeSigningRequirement: nil)
serviceListener.setMessageHandler(name: "some function name", handler: someHandler)


func someHandler(_ connection: XPCConnection, packedArguments: SomeCodableArgumentToPass) {
// boiler plate callback 
   let remoteConnection = try XPCConnection(
            type: .remoteServiceFromEndpoint(packedArguments.callback),
                    codeSigningRequirement: nil
                )
        remoteConnection.activate()
        for await d in Timer.publish(every: 1, on: .main, in: .default).autoconnect().values {
              ... do something ....
            try remoteConnection.sendOnewayMessage(message: SomeCodableResponse(....))
        }
}

Perhaps it would be possible to wrap somethings in macros and eliminate the boiler plate? or perhaps some reflection with naming conventions?

Thoughts?

@CharlesJS
Copy link
Owner

That's a good point; I came up with the plan for this project before macros were available in Swift, so it's possible that there might be some area for future streamlining along those lines. I'll have to ponder over that for a while.

I didn't want to go the reflection route, because I kind of wanted to get away from the excessively "magical" way that NSXPCConnection works. The relative simplicity of this approach appeals to me, as it makes it less likely for weird bugs to show up, as well as probably performing a little better.

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

No branches or pull requests

2 participants