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

Add Glacier2Connection for interop with Glacier2 #3608

Open
bernardnormier opened this issue Aug 22, 2023 · 8 comments
Open

Add Glacier2Connection for interop with Glacier2 #3608

bernardnormier opened this issue Aug 22, 2023 · 8 comments
Labels
proposal Proposal for a new feature or significant update
Milestone

Comments

@bernardnormier
Copy link
Member

Currently, an IceRPC client cannot talk to a server behind Glacier2. I propose to remove this limitation by implementing a new terminal invoker, Glacier2Connection.

Glacier2Connection is similar to a ClientConnection: it maintains a connection to a Glacier2 router. Unlike ClientConnection, Glacier2Connection also associates and maintains a Glacier2 session with its active protocol connection.

The Glacier2ConnectionOptions would be similar to ClientConnectionOptions, with a few additional properties such as:

public bool AuthenticateWithSsl { get; set; }
public string UserName { get; set; } = "";
public string Password { get; set; } = "";
public ServerAddress? ServerAddress { get; set; } // the server address for the Glacier2 router

We also need to figure out a way to return the session proxies to the application, especially upon reconnection. We could provide an action:

public Action<Glacier2.SessionProxy?>? OnNewSession { get; set; }

But that's not great if we want to allow the application to perform async calls on this session before the connection is fully connected and the first "InvokeAsync" goes through. So maybe instead:

public Func<Glacier2.SessionProxy?, Task>? OnNewSession { get; set; }

We could also provide a hook for the protocol connection shutdown. E.g.

// second task = ShutdownRequestedTask
public Func<Glacier2.SessionProxy?, Task, Task>? OnNewSession { get; set; }
@bernardnormier bernardnormier added the proposal Proposal for a new feature or significant update label Aug 22, 2023
@bernardnormier bernardnormier added this to the 0.2 milestone Aug 22, 2023
@bentoi
Copy link
Contributor

bentoi commented Aug 28, 2023

We also need to figure out a way to return the session proxies to the application

Do we actually need to return the actual session proxy returned by Glacier2? Could we instead return a proxy that is valid for the lifetime of the Glacier2Connection instance?

@bernardnormier
Copy link
Member Author

We could but would this provide a better API?

With public Func<Glacier2.SessionProxy?, Task>? OnNewSession { get; set; }, we give the application the ability to perform a post-session-reconnect initialization, using the new per-session proxy, instead of hiding it inside our own wrapper.

@pepone
Copy link
Member

pepone commented Aug 30, 2023

How do you view the registration of client-side services? With Glacier2, you need to use the randomly assigned client category for the callbacks, which changes with each new session.

Could we instead return a proxy that is valid for the lifetime of the Glacier2Connection instance

I believe the session proxy can remain valid; the new session callback is only required for applications using callbacks. For example, if you send a proxy to the server, it will no longer be valid after you create a new session.

@bernardnormier
Copy link
Member Author

bernardnormier commented Aug 30, 2023

How do you view the registration of client-side services?

The application performs all post-session-recreation initialization in the OnNewSession function it registers.

Obviously this category mechanism is not well suited to the Router dispatcher and we may need to provide another Router-like dispatcher that is more appropriate for this use-case.

I believe the session proxy can remain valid;

?

The session manager that Glacier2 uses (if it uses one) will return a new session service/proxy for each new session/connection. We can return a wrapper that hides this creation/replacement (as Benoit suggested). The question is:

  • which API returns this wrapped session proxy?
  • is wrapping this session proxy really more convenient for the caller?

@bernardnormier
Copy link
Member Author

For example, if you send a proxy to the server, it will no longer be valid after you create a new session.

That's really an implementation choice / limitation. Since the Glacier2 categories are UUID-like, you could imagine that an old category remains valid even after reconnection. You do however need to "fix" the connection in the fixed proxy held by the server.

@pepone
Copy link
Member

pepone commented Aug 30, 2023

Since the Glacier2 categories are UUID-like, you could imagine that an old category remains valid even after reconnection.

These categories are not valid after the session expires, as glacier2router uses them to forward calls to the appropriate client connection.

The session manager that Glacier2 uses (if it uses one) will return a new session service/proxy for each new session/connection.

I was thinking it could be a regular proxy, There is nothing special about it, you just need to use Glacier2Connection instead of a regular invoker

@bernardnormier
Copy link
Member Author

Since the Glacier2 categories are UUID-like, you could imagine that an old category remains valid even after reconnection.

These categories are not valid after the session expires, as glacier2router uses them to forward calls to the appropriate client connection.

You're right.

The session manager that Glacier2 uses (if it uses one) will return a new session service/proxy for each new session/connection.

I was thinking it could be a regular proxy, There is nothing special about it, you just need to use Glacier2Connection instead of a regular invoker

It's a regular per session proxy. The session manager (that you configured with the Glacier2 router) can return a UUID service each time Glacier2 calls it.

@bernardnormier
Copy link
Member Author

bernardnormier commented Sep 1, 2023

See:
https://github.com/zeroc-ice/ice/blob/badafe8b848181a720ab96b48da6abc170fd918c/slice/Glacier2/Router.ice#L70
https://github.com/zeroc-ice/ice/blob/badafe8b848181a720ab96b48da6abc170fd918c/slice/Ice/Router.ice#L38

The way I see it, Glacier2Connection would NOT expose the Glacier2 router proxy at all to the application. This proxy is an implementation detail of Glacier2Connection.

The application just needs to configure its server address with:

public ServerAddress? ServerAddress { get; set; } // the server address for the Glacier2 router

Then, for "callbacks" (= requests sent by servers behind Glacier2 to the client via Glacier2Connection):

This can be a Slice service, a Router, whatever, as usual.

  • Glacier2Connection removes the current category (/category) from the path of all incoming requests
    This way, the application can reuse the same Router for multiple sessions.

  • the OnNewSession option becomes:

public Func<Glacier2.SessionProxy?, string, Task, Task>? OnNewSession { get; set; }

where string = category for this session (see Glacier2::Router::getCategoryFromClient)
second task = ShutdownRequestedTask

The OnNewSession registered by the application makes calls to servers (via the Glacier2Connection) to (re)register callbacks (proxies) with remote servers.

One difficulty is there is no obvious way to distinguish between these OnNewSession invocations and regular invocations, so:
i) do we let regular invocations through too?
ii) do we provide a special Invoker for these initialization?

I think a separate initialization phase would be cleaner. The downside of the special invoker is it forces the application to deal with multiple invokers / invocation pipelines. Note that we also need such a special invoker for the session proxy.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
proposal Proposal for a new feature or significant update
Projects
None yet
Development

No branches or pull requests

3 participants