Can I use AQL to get a list of deleted compositions?
regards
Can I use AQL to get a list of deleted compositions?
regards
Iām not an AQL user, but I think that in theory yes you should be able get them, through VERSION and its lifecycle_state
attribute.
On the other hand I am curious about the use-case you have, and if some other REST API ways (which we donāt have yet) might suit better.
Thanks. Any thoughts on what the path for lifecycle_state?.
The use case is for audit purposes to get a list of deleted compositions. If we cannot get this list, what is the purpose of maintaining the versions of a deleted composition? Unless we keep a list somewhere outside, we will never be able to know that they exist for any audit or forensics.
regards
That AQL I would guess it should contain something like:
....
FROM EHR e
CONTAINS VERSION v [LATEST_VERSION]
CONTAINS COMPOSITION c
WHERE
v/lifecycle_state/defining_code/code_string = 523
...
About the use-case, I think it sounds very much reasonable, and is exactly for what I was looking as a feedback to improve REST specifications, as alternative to get this data without the of AQL. For instance in this case a GET /ehr/{ehr_id}/composition?lifecycle_state=deleted
(thus retrieve all deleted compositions) or a GET /admin/ehr/{ehr_id}/contribution?audit_details.change_type=deleted
(admin-level get all contribution that were about content soft delete) might make some sense. Any suggestion ?
Thank you very much. I will try this out
As for you suggestions on REST APIs, I think they both are very good suggestions.
GET /ehr/{ehr_id}/composition?lifecycle_state=deleted will be useful at runtime for audits and review in the context of a patient. However this can return an array of empty compositions(maybe even versioned compositionIds). Our current get composition API returns one composition. In fact as a general practice openEHR REST APIs seem to operate only on a single resource. So we may have to think of a new set of apis that operate on an array.
GET /admin/ehr/{ehr_id}/contribution?audit_details.change_type=deleted This is another interesting idea for a system wide monitoring & administration. In fact this can be extended to include other change_types and also additional query params such as ehr_id to make it more generic. However the REST specs currently do not seem to have any admin APIs and so this has to be considered in the context of a broader admin functionality. Currently implementers such as EHRBase seem to have their own strategies around admin operations. Some level of standardization on this can also be considered
regards
Hi,
On a related note,
As per specs, when we do a get on a deleted composition, we return 204 with no content. The response does not explicitly inform that the composition is deleted and the user has to infer that it is deleted from the null body response.
This, I feel is counter intuitive for users. Normally REST APIs either responds with 404 not found or in systems that version data, explicit message that it has been deleted(FHIR). Any thoughts on this?
regards
ā204 No Content is returned when the resource identified by the request parameters (at specified version_at_time) time has been deleted.ā
IMO there is nothing to infer, the rule is clear: 204 implies itās deleted.
404 seems incorrect in this context since the COMPO exists.
Personally, I donāt see an issue with the current spec.
Though, if we would like to do GETs on deleted COMPOs and get some content, thatās a new requirement. One workaround is that: if you have the VERSION.uid of the deleted COMPO, you could GET the previous version that will have content, and since the DELETE doesnāt change the content, thatās the content of the deleted COMPO. A more secure way to get the previous version is to use the āGet versioned COMPOSITION revision historyā endpoint. Another way would be to have an admin endpoint to read deleted COMPOs, this currently doesnāt exist AFAIK.
Hope that helps.
Best,
Pablo.
For what itās worth @Dileep, Iām on your side on this!!
https://openehr.atlassian.net/browse/SPECITS-50
As @Pablo has said, strictly speaking, the 204 behaviour is correct, and I understand that FHIR does the same thing on a DELETE.
However, I and others have found that it does cause regular confusion in dev community, esp in the context of POSTs because the āminimalā response header does allow no content to be returned, and āminimalā has never been standardised.
The answer might be to add a āstandardā response type as a default, which requires some kind of minimal content to be returned, typically the ID of a new EHR or Composition, or the name of the committed Template and will therefore generate a 201.
Iām not so sure about DELETE
but Iād still favour some sort of āstandardā response that indicates that the Delete has been successful along with an explicit response and a 200. If people want to use minimal with no-content, thatās fine but it really seems quite counter-intuitive for a lot of devs.
If there is a requirement to explicitly get deleted locatables, COMPOs etc. I think the ADMIN API would be a better place than a GET in the normal API. My rationale is: with the current specs itās clear in which conditions the GET returns No Content and that is for DELETED COMPOs. So if the contents of the DELETED COMPO are required, I would say the reason might be more for management/audit purposes than normal API interaction (CRUD), thatās why I think the ADMIN API is a better place for this requirement. Though as said before, by using the previous version the contents can be retrieved (see my previous comment).
Iām not sure why developers get confused around this, the spec IMHO is clear and unambiguous, it just needs to be read in full, and of course if there are doubts, there is a friendly community here to help out
Hi,
I fully agree that the specifications mention returning 204 for deleted compositions and since 204 specs does not allow content, our specs are conforming to the RFC. Where I beg to differ is if this response is self explanatory for all developers.
In that I believe that the specifications can be updated to make it more intuitive for app developers who consume and work with this API. I also believe that HAPI FHIRās handling of the same situation is more elegant. It returns 410 Gone with a body with more details(screenshot attached) , which informs that the resource is Gone(different from 404) to the user.
This also aligns with the openEHR deletion strategy, where once deleted, the composition is not accessible via the GET and QUERY interfaces, which makes it literally gone for all practical purposes.
regards
That was not really what I was suggesting. For Posts/Puts it does make sense to me that we should (as default) expect the PII to return some sort of acknowledgement of success along with the ID of the created object.
For DELETE, a simple notification of suces as per the FHIR example, would be sufficient.
I know that 204 is ācorrectā but like it or not quite a few of us are finding that it is confusing developers, particularly those increasing numbers who are not well versed in openEHR or the A:I. THey just donāt expect it to work this way, based on prior experience.
My suggestion is that we need to agree on āactualā minimal content as the default response to most API calls. No-content 204 responses are still acceptable but as a choice.
The bigger problem here is that a deleted version does not technically contain a composition (v/data is empty for such a version), so this would return nothing. At least our (Better) implementation works that way. A further problem there is that you can not then query for, say, all deleted composition of a certain template_id, because there is no c/archetype_details/template_id/value
. There is a trunk_lifecycle_state
on a VERSIONED_OBJECT
(like VERSIONED_COMPOSITION
) though, see Common Information Model. (Itās defined as a function, but we expose it as an attribute.) So you can do:
SELECT c
FROM VERSIONED_OBJECT vo
CONTAINS VERSION v[all_versions]
WHERE vo/trunk_lifecycle_state/defining_code/code_string = 523
This, however, will give you all the versions of such compositions. You are probably only interested in the last version before the act of deletion, which we make possible in a non-standard way through is_last_version
AQL function by adding another where condition is_last_version(s, includingDeleted = false)
.