forked from OpenAssetIO/OpenAssetIO
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
[Docs] Add DR covering canonical use of
managementPolicy
.
Part of #778, this aspect of the API has not been documented in any detail. Signed-off-by: Tom Cowland <tom@foundry.com>
- Loading branch information
1 parent
01ed453
commit 7535934
Showing
1 changed file
with
255 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,255 @@ | ||
# DR014 Management Policy responses | ||
|
||
- **Status:** Decided | ||
- **Driver:** @foundrytom | ||
- **Approver:** @feltech @ecmorris @antirotor @mattdaw | ||
- **Outcome:** A Manager should additionally imbue a `managementPolicy` | ||
response with the traits that it is capable of resolving for each | ||
trait set. | ||
|
||
## Background | ||
|
||
The ability for a host to query a manager's capabilities and intent is a | ||
critical part of the OpenAssetIO abstraction. | ||
|
||
OpenAssetIO classifies entities (assets) using a Trait Set, which lists | ||
one or more traits that describe it's nature. For example, and image | ||
file may have the trait set `{'file', 'image', 'raster', | ||
'colorManaged'}`. | ||
|
||
The `managementPolicy` method is a high-level (i.e. not entity specific) | ||
query that a host can use to determine a manager's behaviour in relation | ||
to a specific trait set. | ||
|
||
The answer to this query is commonly used by a Host to conditionally | ||
enable user-facing functionality based on the behaviour of the specific | ||
manager that is in use. | ||
|
||
This mechanism is flexible, and so exactly how a manager should | ||
implement its response is potentially ambiguous. This document outlines | ||
the rationale behind the defined canonical behaviour. | ||
|
||
## Relevant data | ||
|
||
Documentation pertaining to the OpenAssetIO data model: | ||
|
||
- [Entities, Traits and Specifications overview](../doxygen/src/EntitiesTraitsSpecifications.dox) | ||
- [Compositional data model decision record](./DR007-Hierarchical-or-compositional-traits-for-specifications.md) | ||
- [Unified Entity data model decision record](./DR008-Unify-the-entity-data-model.md) | ||
|
||
Notable points: | ||
|
||
- Trait sets combine multiple traits to increase specificity, rather | ||
than meaning "or". | ||
- Some managers may only care about certain specific traits (such as | ||
those describing the assets content disposition), and handle all | ||
'derivative entity types' the same. | ||
- The `managementPolicy` query is not a required pre-requisite in the | ||
use of `resolve`, et. al. but is used to adapt application behaviour | ||
to improve user experience. | ||
|
||
## Illustrative scenario | ||
|
||
Consider a manager that pivots all behaviour around a | ||
`file` trait - that defines that any entity with that trait stores its | ||
data in a file. The manager's sole purpose is to manage the paths of | ||
such entities. It is not interested in any other kinds, and should not | ||
be involved in there creation or management. | ||
|
||
As such, it wishes to opt-in to the management of any file-based entity, | ||
regardless of its specific trait set. | ||
|
||
The manager fulfills the API contract, by storing an entities trait set | ||
in its database - allowing it to filter lookups by trait set, and | ||
properly re-classify any given entity as required, but it can't store | ||
arbitrary data, and so can't persist the data for any other traits. | ||
|
||
A Host that manages several file-based entities (eg: its | ||
main document and assorted data files that it reads/writes), | ||
will query the manager's `managementPolicy` to determine for which of | ||
these the manager should be involved with. | ||
|
||
If a manager opts-out of managing any given trait set, then the host | ||
will use its native UI/workflows for browsing and saving, if it opts-in, | ||
then it will delegate UI and data locality responsibilities to the | ||
manager. | ||
|
||
So, how should this manager respond to the `managementPolicy` query for | ||
any specific trait set? | ||
|
||
Lets explore the scenario where the host is querying the manager's | ||
policy for it's native document format, and for images it generates: | ||
|
||
```python | ||
traitSets =[ | ||
{ 'file', 'nodeGraph' }, # Main document | ||
{ 'file', 'image', 'raster', 'colorManaged' } # Generated images | ||
] | ||
``` | ||
|
||
## Options considered | ||
|
||
### Option 1 - Any Matching | ||
|
||
It should respond on the basis of matching any of the traits in the set, | ||
even if it doesn't understand many others: | ||
|
||
```python | ||
if FileTrait.kId in traitSet: | ||
ManagedTrait.imbueTo(policy) | ||
``` | ||
|
||
Such that it opts-in to managing all entities with the file trait in | ||
their set. | ||
|
||
```python | ||
policies = [ | ||
{ 'managed': {...} }, # Main document | ||
{ 'managed': {...} } # Generated Images | ||
] | ||
``` | ||
|
||
Any other queries for trait sets without the file trait would be empty | ||
`{}` indicating un-managed status. | ||
|
||
#### Pros | ||
|
||
- Hosts can query specific and precise trait sets, but the manager does | ||
not need to worry about all possible permutations. | ||
|
||
#### Cons | ||
|
||
- There is no way for a host to determine what traits can be resolved | ||
(or persisted) for any given entity, and so must tolerate missing data | ||
at a later date (e.g. the color space for the `colorManaged` trait, if | ||
the manager can't ever provide this). | ||
|
||
### Option 2 - Exact Matching | ||
|
||
It should respond only to sets where it is capable of resolving or | ||
persisting the required data: | ||
|
||
```python | ||
if traitSet == { FileTrait.kId }: | ||
ManagedTrait.imbueTo(policy) | ||
``` | ||
|
||
Such that it _only_ opts into managing the specifically limited trait | ||
set that it can support: | ||
|
||
```python | ||
policies = [ | ||
{}, # Main document | ||
{} # Generated Images | ||
] | ||
``` | ||
|
||
The Host would receive empty responses (`{}`) for both the original | ||
trait sets, and so must potentially degrade and re-try its queried trait | ||
set if it is happy with only a subset. e.g: | ||
|
||
```python | ||
traitSets = [ | ||
{ 'file', 'nodeGraph' }, # Main document | ||
{ 'file', 'image', 'raster', 'colorManaged' }, # Generated images | ||
{ 'file', 'image', 'raster' }, | ||
{ 'file', 'image' }, | ||
{ 'file' } # File | ||
] | ||
``` | ||
|
||
Resulting in: | ||
|
||
```python | ||
policies = [ | ||
{}, # Main document | ||
{}, # Generated Images | ||
{}, | ||
{}, | ||
{ 'managed': {...} }, # File | ||
] | ||
``` | ||
|
||
#### Pros | ||
|
||
- Conveys only what traits are supported to the host, allowing | ||
behaviour to be properly adapted to the manager's capabilities. | ||
|
||
#### Cons | ||
|
||
- Host implementation is significantly more complicated. | ||
- No way to hint at any additional traits that may be resolvable | ||
outside the typing trait set. | ||
|
||
### Option 3 - Supported Traits Response | ||
|
||
The host should also include any additional traits that it may attempt | ||
to resolve in the future, e.g. if it supported the ability to customise | ||
t,he file format used for writing images, by resolving a custom trait: | ||
|
||
```python | ||
traitSets =[ | ||
{ 'file', 'nodeGraph' }, | ||
{ 'file', 'image', 'raster', 'colorManaged', 'fileFormatOptions' } | ||
] | ||
``` | ||
|
||
The manager should respond as per Option 1, but in addition, imbue any | ||
of the queried traits that the manager is capable of resolving: | ||
|
||
```python | ||
if FileTrait.kId in traitSet: | ||
ManagerTrait.imbueTo(policy) | ||
FileTrait.imbueTo(policy) | ||
``` | ||
|
||
This would then look like the following: | ||
|
||
```python | ||
policies = [ | ||
{ 'managed': {...}, 'file': {} }, # Main document | ||
{ 'managed': {...}, 'file': {} } # Generated Images | ||
] | ||
``` | ||
|
||
This indicates that the manager would like to handle interactions for | ||
entities with these traits sets, but it can only resolve the `file` | ||
trait. | ||
|
||
> Note: | ||
> We keep the concept additionally imbuing the `managed` trait | ||
> (though it may seem superfluous, as an empty trait set is equivalent to | ||
> un-managed) as in practical use cases it may well have other properties | ||
> that cover topics such as exclusivity/etc. | ||
> There are also additional traits that may be imbued by the manager to | ||
> determine how it handles various aspects of the publishing process, | ||
> e.g. thumbnails. | ||
#### Pros | ||
|
||
- Explicit communication of exact capabilities, so hosts and managers | ||
can suitably adapt behaviour. | ||
- Facilitates functional workflows where the result of `managementPolicy` | ||
can be passed as the requested trait set for `resolve`. | ||
|
||
#### Cons | ||
|
||
- Implementation in the manager and host may be slightly more involved | ||
than other options in some scenarios. | ||
|
||
## Outcome | ||
|
||
The `managementPolicy` mechanism should always be queried with the full | ||
trait set for any given entity specification, and any additional traits | ||
a host may attempt to resolve for that type (if known). | ||
|
||
The response populated by a manager should include all resolvable traits | ||
from that set, along with any additional traits that describe the | ||
manager's behaviour. | ||
|
||
## Rationale | ||
|
||
This offers the best of both worlds. It provides the highest quality | ||
information to both hosts and managers, whilst keeping the additional | ||
programming overhead to a minimum. It allows both parties to adapt their | ||
business logical in an explicit and coordinated fashion. |