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

Allow studio ui to set globals + expose session state returned by the server #651

Merged
merged 2 commits into from
Jun 15, 2023

Conversation

jaclarke
Copy link
Member

No description provided.

Copy link
Collaborator

@scotttrinh scotttrinh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No blockers, a few questions.

@@ -143,6 +143,8 @@ class BaseFetchConnection extends BaseRawConnection {
}

export class AdminUIFetchConnection extends BaseFetchConnection {
cliMode = true;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What is the relationship between the names cli and AdminUI here? Can/should this flag be named adminUiMode or are there some other cli commands that would also run in this mode in the future?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The name cliMode was because it opts in to the cli behaviour where we actually read any updated session state the server returns instead of discarding it (though in theory it should never return updated state anyway for normal client usage). But we can call it adminUIMode if that makes more sense. It's a private api, only going to be used by the ui anyway.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker, for sure. Other options: emulateCli, useCliBehavior, etc. Definitely not a hard requirement and adminUiMode isn't much more enlightening than cliMode now that you've explained it.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think adminUiMode is probably the better name. I don't think we're likely to add anything else separate from the ui that will need the 'cli behaviour', and it's possible we'll need to add more hacks in the future for the ui that are not 'cli like'.

@@ -134,6 +140,9 @@ export class BaseRawConnection {

protected stateCodec: ICodec = INVALID_CODEC;
protected stateCache: [Session, Uint8Array] | null = null;
protected lastStateUpdate: any = null;
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not a blocker: is there a more specific type we can use here? Since it doesn't look like we're accessing it at runtime, could we use unknown instead?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The exact type depends on the schema, but yes, we could have something a bit more specific like:

{
  globals?: {[name: string]: any},
  config?: {[name: string]: any},
  aliases?: [string, string][]
}

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Unless we need to use it in runtime code, my vote is for unknown since it's the simplest possible safe type here. Otherwise, if there is a common interface for this property that we might want to use in the future, now seems like a good time to give this a name while we're in here.

And, to reiterate, my preference for those record types would be Record<string, unknown> rather than { [name: string]: any } just to require downstream checking if anything ever did want to access a property.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yep, good point. It does share the type with the session state we send, which is currently typed as any. And aside from changing any -> unknown which makes sense, is there a reason to use Record<Key, Type> over {[key: Key]: Type}? For me the second seems more useful, since it can have a hint of what the key represents, eg. is it a mapping of 'names' or 'ids' to something.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, sure, I just thought name was a throwaway identifier 😆. I mostly prefer the Record syntax because it communicates to me that it's just a record rather than having some hidden mapped type magic that I should check for, so makes it a little easier to glance at. Not a big deal for me either way.

Comment on lines 295 to 299
if (this.cliMode && stateTypeId === this.stateCodec.tid) {
this.lastStateUpdate = this.stateCodec.decode(
new ReadBuffer(stateData)
);
}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's possible that I just don't understand what the context of this feature is, but can I have a quick tl;dr on what these new properties are for?

Copy link
Member Author

@jaclarke jaclarke Jun 15, 2023

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Some protocol context: Normally for clients the session state (ie. globals, aliases and session config (like apply_access_policies)) is managed entirely client side via the client.with* api's, then encoded and sent with every query (since the protocol is stateless except for transactions). However for the cli, there's obviously no programmatic api to set this state, so instead you use the set global/alias/module ... and configure session ... commands in edgeql, and when you run one of these commands the server returns an updated session state object, which the cli stores and sends back with following queries.

And the context for this PR: Currently the UI repl follows the client behaviour, where session state is set entirely in the UI. But we want to allow the edgeql commands to work, so this PR allows the private api's the ui uses to enable this hybrid client/cli behaviour by:

  • Allowing the rawParse/rawExecute methods to set custom capabilities flags, so the server won't reject the edgeql commands
  • Actually decoding the updated state the server returns. I'm just storing this updated state in a lastStateUpdate property on the connection (similar to lastStatus), mainly so I don't add any complexity by having to thread it through as a return value along with the actual result from the execute method.
  • Adding a cliMode flag so the above decoding is only enabled for the ui. And also it disables an optimisation where we don't send the session state if nothing's been set, since we need the server to send an updated codec to decode the session state, as we actually need to read it now.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Great, thanks for the additional context! 🙏

Copy link
Collaborator

@scotttrinh scotttrinh left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Love it! 🏆

@jaclarke jaclarke merged commit a05d11c into master Jun 15, 2023
8 checks passed
@jaclarke jaclarke deleted the session-state branch June 15, 2023 20:26
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

Successfully merging this pull request may close these issues.

None yet

2 participants