-
Notifications
You must be signed in to change notification settings - Fork 132
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
Extend AppD application definition to support describing an app's use of interop (App Channels, User Channels & Intents) #247
Comments
@kriswest |
I think we're still a little premature on this one considering ongoing discussions around feeds, transactions and an upcoming proposal on providing utilities through channels. Immediately, one can see an ambiguity in this proposal because it does not allow an app definition to declare whether context listen/broadcast occurs only on system or app channels. The use case is aspirational rather than current world and so I don't think there is much harm in deferring decision on this one until there is more clarity in regard to how 2.0 will shape channels. |
@thorsent this only applies to system channels - although I did not figure out a way for that to be obvious through the configuration alone - perhaps swap out e.g. {
"appId": "string",
"name": "string",
...
"intents": [
{
...
}
],
"system-channels":
{
"broadcast": [
"string"
],
"listen": [
"string"
]
},
"app-channels": [
{
"name": "myChannel",
"description": "Description of what this channel is used for"
"broadcast": [
"string"
],
"listen": [
"string"
]
}
]
} I am happy to defer this issue and #371 until we know what we're doing about a better definition of channels (#376) as that will have an impact on what the configuration should be. I do however want to see this done in 2.0 so that we do it alongside the other refinements of appD proposed. |
Very much agreed on hammering out appd as complete as possible for 2.0. |
Added to 2.0 milestone after informal vote. |
Issue #371 was merged into this issue and its description extended to cover various ways that details of interop use could be added to appD |
Given the feedback at the last AppD meeting #664 I've taken another look at the structure of this optional metadata. We can either refine the naming and stick with it usage first (usage type: interaction[context]): {
"appId": "string",
"name": "string",
...
"intents": [ // existing intents element
{
"name": "string",
"displayName": "string",
"contexts": [ "string" ],
"customConfig": {}
}
],
"interopUse": { // new interopUse element
"raisesIntents": {
"string" : [ "string" ] //intent: [ contextType1, contextType2 ]
},
"raisesContexts": [ "string" ] //[ contextType1, contextType2 ]
"userChannelContexts": {
"broadcast": [ "string" ], // [ contextType1, contextType2 ]
"listen": [ "string" ] // [ contextType1, contextType2 ]
},
"appChannels": [
{
"name": "string", // channel name (as used with `fdc3.getOrCreateChannel`)
"description": "string", // description of channels purpose/usage
"broadcast": [ "string" ], // [ contextType1, contextType2 ]
"listen": [ "string" ] // [ contextType1, contextType2 ]
}
]
}
} or we can flip it around and go with context: interaction[ channel ] {
"appId": "string",
"name": "string",
...
"intents": [ // existing intents element
{
"name": "string",
"displayName": "string",
"contexts": [ "string" ],
"customConfig": {}
}
],
"contextUse": { // new contextUse element
"fdc3.instrument": {
"raiseIntent": [ "ViewChart", "ViewOrders", "ViewTrades", "any" ] //"any" represents raiseIntentForContext
"broadcast": ["user", "customChannelName"], //"user" represents user colour channels
"listen": ["otherCustomChannelName"]
},
"fdc3.order": {
"raiseIntent": [ "Createorder", "ViewOrder" ]
}
}
} Does the latter make more sense? |
I think the former is superior because it doesn't rely on magic strings and neatly defines app channels. Personally I would prefer if |
@nkolba regarding your comment at
{
"appId": "string",
"name": "string",
...
"intents": [ // existing intents element
{
"name": "string",
"displayName": "string",
"contexts": [ "string" ],
"customConfig": {}
}
],
"raiseIntent": { //new element for intent and context pairs raised
"string" : [ "string" ] //intent: [ contextType ]
},
"raiseIntentForContext": [ "string" ], // [ contextType ] new element for contexts passed to fn
"userChannels": { //new element for context use on user channels
"broadcast": [ "string" ], // [ contextType ]
"listen": [ "string" ] // [ contextType ]
},
"appChannels": [ //new element for name of and context use on app channels
{
"name": "string", // channel name (as used with `fdc3.getOrCreateChannel`)
"description": "string", // description of channels purpose/usage
"broadcast": [ "string" ], // [ contextType ]
"listen": [ "string" ] // [ contextType ]
}
]
} If that deals with your concerns, I'll update the PR with it |
This is an area I've been struggling with in FDC3. From talking to @nkolba about his implementation, he's told me that he's currently doing this work programmatically. So, given this instrument: ... his However, the above Issue / PR aims to make all this work declaratively - i.e. the desktop agent has enough meta-data about the applications to figure this out without callbacks. -- Am I right about this? From an app-development perspective, I think it might be better to "pick a lane" and choose one way or the other, otherwise this could get really confusing really fast. |
Not exactly, no. There's possibly a crossed-wire in that conversation. Intent resolution is declarative already (since FDC3 1.0) in that the This PR addresses a different use case - finding apps that work together, in an app browser or launcher (e.g. other apps that 'work with' this one). We have the above declarative config of what intent/context pairs an app will receive... but we don't know what they raise (until they've done it). Hence, we can't look at the app (say an OMS) and say this chart or alert tool etc. will work with it, because we don't know what requests we're going to make. Thats one example, we also have this gap on channels: we don't know what app channels an app will create, whether it uses user channels at all and what contexts are exchanged. If we have that information we can find other apps that will work with it. TL;DR: This PR doesn't change how the desktop agent works. It just aims to (allow a developer/publisher to) provide more metadata on how an app interoperates so that an app directory browser can find you other apps that will work with it. Finally, see this note in the additional info section of the issue (a similar note is incorporated into the documentation of each field added):
|
I propose we remove
Basically I'm just echoing what I said in the earlier comment: you're repeating what you're doing programmatically, it's going to be a pain for app developers to keep this straight as their app changes. I've been down this road with manifests before, and ended up trying to automate the manifest creation with code in order to avoid discrepancy. Recalling the meeting, @nkolba worries this violates DRY and I'm kind of with that. Moreover, I don't think it's possible to say with complete certainty whether you are consuming or producing a particular context type - often it will be both or neither at different times and under certain conditions, depending on the code of the callback. As usual, just my outsider opinion... I can also see the argument for leaving this out of 2.0, for example. |
my proposal would be to
Here are a couple of possibilities: {
"appId": "string",
"name": "string",
...
,
"interopMeta": { // new interopUse element
"listensForIntents": [ // replaces existing intents element
{
"string" : [ "string" ] //intent: [ contextType ]
}
],
"raisesIntents": {
"string" : [ "string" ] //intent: [ contextType ]
},
"listensForContexts":
[ "string" ], // [ contextType ]
,
"broadcastsContexts":
[ "string" ], // [ contextType ]
,
"createsChannels": [
{
"name": "string", // channel name (as used with `fdc3.getOrCreateChannel`)
"description": "string", // description of channels purpose/usage
"broadcast": [ "string" ], // [ contextType ]
"listen": [ "string" ] // [ contextType ]
}
]
}
} maybe a bit more elegant: {
"appId": "string",
"name": "string",
...
,
"interopMeta": { // new interopUse element
"listensFor": {
intents {. // replaces existing intents element
"string" : [ "string" ] //intent: [ contextType ]
},
"contexts": {
[ "string" ], // [ contextType ]
}
},
"raises": {
intents {.
"string" : [ "string" ] //intent: [ contextType ]
},
"contexts": {
[ "string" ], // [ contextType ]
}
},
"creates": {
"channels": [
{
"name": "string", // channel name (as used with `fdc3.getOrCreateChannel`)
"description": "string", // description of channels purpose/usage
"broadcast": [ "string" ], // [ contextType ]
"listen": [ "string" ] // [ contextType ]
}
]
}
}
} This completely breaks the way intents are handled in appD today - which means that the desktop agent will need to do some more work to go from an appD query to a resolver object in the client. However, with the addition of the 'intents' and 'contexts' endpoints - there is a now a better way to retrieve this metadata. |
We can't extract what they are doing programmatically, particularly before the app is ever launched (the use case for this data is discovery of apps), so they need to maintain a list. As stated in the proposal's docs, the data is optional and doesn't break anything (other than discovery ;-) ) if it's not correct. A developer would have to extract the same information to document their integration... and if you can't document your integration points then you've got bigger problems. The goal here was to provide an (optional) standard place to document the app's behaviour so that it can be used to discover other apps that it will interop with and to make it easier to find.
It disagree as this is configuration describing the behaviour of code. It's not repeating something (like defining 3 copies of a function, or documenting the same behaviour in 3 places would be) it's referencing it (specifically the use of certain API functions). Referencing something using a different term to avoid repeating it seems odd to say the least.
The way the FDC3 API works you are capable of either listening for something, broadcasting it or both. Theres not really any uncertainty about that as you have to make different API calls for the actions. Further, you are describing what the app is capable of doing here, not what it did when a user took a particular set of actions, which should simplify the task. It should be everything your app can do with the FDC3 API, that you want to tell other about. @nkolba we do seem to have come (almost) full circle on the proposal as the proposed I doubt we've got time to get this into 2.0 (particularly with an additional breaking change that I think we'll get pushback on), but I'll tack an 'if time' item on to the SWG agenda for it. A PR will need to be ready for it. I'll have another look at the comments and proposal tomorrow and see if I feel differently about any of it. |
@kriswest at the risk of dating myself: "the way forward is sometimes the way back" :) Really, I think we're very close:
I think where we aren't agreed is on how this maps/doesn't map to the API and the key sticking point with that is 'raiseIntentForContext'. My POV is that if an app is already declaring what intents & contexts it raises and listens for, then I don't see the value in an app declaring "I call 'raiseIntentForContext' with these context types" (over "I raise/broadcast these kinds of contexts") I am just failing to see how an app developer would make such a nuanced distinction and what a platform owner would do with such a declaration (especially since the metadata is self-declared and therefore never going to be fully solid). Finally, my concern would be that this takes us down a slippery slope of representing more and more APIs in the app record - making that records more prone to error and ambiguity and more confusing for adopters. One final thought: it could be useful to introduce a generic 'meta' block as a partial solution for some of these questions. This would allow different directory implementations to extend the interop metadata they support outside of the standard. I.e.
|
I'd also like to clarify the use cases a little (in part to clarify why I don't want to simplify as @robmoffat proposed), I think there are two:
I think that by working with the API calls as labels the distinction is pretty clear for a developer (I call this function with that type). Whereas, by blurring the lines between the different types of interaction it seems, at least to me, much harder for a developer to work out what they should be declaring where (and if using this info to plan an integration, much much harder to work out if you need to broadcast or raise an intent). I may be misinterpreting that from the example however. In your latter proposal are you lumping I'm ok with compromising here (although I'd like to keep intent handling separate from user channel contexts). I think we need to sort out how they declare what they broadcast on user channels and then stick to the same style in the declaration of what they do on an appChannel. Hence, how about these alternatives? Acontinue conflating intent listening with user channel listening, but separate broadcast on user channels... {
appId: "string",
name: "string",
//...
interopMeta: { // new interopMeta element
listensFor: { //covers both intents and user channels
intents: { //replaces existing intents element
string: ["string"],
},
contexts: ["string"] //relates to user channels
},
raises: { //intents only
intents: {
string: ["string"],
},
contexts: ["string"]
},
broadcasts: ["string"], // user channels only
appChannels: [ //app channels
{
name: "string",
description: "string",
listensFor: ["string"],
broadcasts: ["string"]
}
]
}
}; Bseparate intents and user channel use (although we end up with {
appId: "string",
name: "string",
//...
interopMeta: { // new interopMeta element
intents: { // intents only
listensFor: { //replaces existing intents element
string: ["string"],
},
raises: { // intents only
intents: {
string: ["string"],
},
contexts: ["string"]
}
},
userChannels: { // user channels only
broadcasts: ["string"],
listensFor: ["string"]
},
appChannels: [ //app channels
{
name: "string",
description: "string",
listensFor: ["string"],
broadcasts: ["string"]
}
]
}
}; Cuse magic string 'any' to simplify intents {
appId: "string",
name: "string",
//...
interopMeta: { // new interopMeta element
intents: { // intents only
listensFor: { //replaces existing intents element
string: ["string"],
},
raises: { // intents only
string: ["string"], //use "any" to represent raiseIntentForContext
}
},
userChannels: { // user channels only
broadcasts: ["string"],
listensFor: ["string"]
},
appChannels: [ //app channels
{
name: "string",
description: "string",
listensFor: ["string"],
broadcasts: ["string"]
}
]
}
}; Personally, I like C best. But either B or C works for me as they keep the 3 interaction types separate (intents, user channels, app channels).
No you're safe, Labyrinth is a timeless classic :-p |
Thanks @kriswest . This makes sense to me. I could go with either B or C as well (and guess I'll have to meet you in the middle on "userChannels" - sigh ;)). |
I forgot intent listeners need result types and some other metadata, such as displayName. Heres a further refinement of C which expands {
appId: "string",
name: "string",
//...
interopMeta: { // new interopMeta element
intents: { // intents only
listensFor: { //replaces existing intents element
"string": { //intent name
displayName: "string",
contexts: ["string"],
resultType: "string"
customConfig: "object"
}
},
raises: { // intents only
"string": ["string"], //use "any" to represent raiseIntentForContext
}
},
userChannels: { // user channels only
broadcasts: ["string"],
listensFor: ["string"]
},
appChannels: [ //app channels
{
name: "string",
description: "string",
listensFor: ["string"],
broadcasts: ["string"]
}
]
}
}; |
issue approved via email vote. See PR #731 for details. |
Enhancement Request
Extend the AppD's Application definition to include details of how an application uses Interop, including:
Use Case:
When assembling a desktop, Users (or desktop implementors) may wish to search an App directory for applications that 'work with' a selected application. This is currently not possible as AppD application records can only provide detail on intent/context combination that can be handled, and does not provide information on intents/context raised, channels or contexts broadcast/listened to on them.
Additionally, app developers or Desktop Agent vendors may wish to be able to build UIs that can
fdc3.open
applications supporting a particular context. This information is known to the desktop agent at runtime after the application has been started, but is not known to either the Desktop Agent or application developer in advance except by direct interaction with the developer/publisher of each application.N.B. additional changes may be needed for the FDC3 API to support the latter use case. However, a first step to doing so is to decide if and how the necessary information is provided to the Desktop Agent.
Workflow Description
A desktop agent or desktop developer may wish to implement functionality that leverages information on what context types are broadcast and listened to by applications in the desktop. E.g. The user browses an Application catalog UI (backed by an AppD instance) to select applications for their desktop and adds one (e.g. a view of the current orderbook developed in-house) to their launcher app. They then wish to find other applications that will work with it, both in an application catalog and via an 'open in ...' function (
fdc3.open
) or 'perform action' (fdc3.raiseIntent
,fdc3.raiseIntentForContext
,fdc3.findIntent
,fdc3.findIntentForContext
) function within the application itself.Workflow Examples
A user (or desktop administrator that manages a desktop for users) is browsing an app catalog to select applications for use on their desktop:
fdc3.broadcast
, the user wishes to see a list of other apps in the application catalog that listen for that context via channel linking (fdc3.addContextListener
)fdc3.addContextListener
, the user wishes to see a list of other apps in the application catalog that broadcast that context via channel linking (fdc3.broadcast
)fdc3.addIntentListener
, the user wishes to see a list of other apps that can raise the intent (with the necessary context)Additional Information (edited 22/04/22)
The Desktop Agent API supports a number of methods of passing context to applications:
However, the AppD spec currently only supports declaring the intents listened for and associated context types and does not provide information on what contexts are supported for
fdc3.open
,fdc3.broadcast
andfdc3.addContextListener
, nor what intents may be raised.To help provide information to a resolver for raiseIntent (where a filtered set of applications that support the intent and context type must be determined), the AppD spec defines an intents element to be used to declare the supported intents and associated contexts. This information is required in order to implement intent resolution within the Desktop Agent. In contrast, the additions proposed by this issue are NOT required for resolving FDC3 API calls and do not imply any form of contract with the Desktop Agent, but are instead useful in implementing an app catalog to render app directory content. As such, providing this information in an AppD record should be considered optional, but recommended (SHOULD).
Proposed additions to the App Directory record (edited 22/04/22):
Note:
The text was updated successfully, but these errors were encountered: