# Held results

Keep results whose case does not exist yet and write them once it does.

This page follows [Results from FHIR](https://zato.io/docs/dev/healthcare/dhis2/lab-results/fhir.html) in the [Lab results](https://zato.io/docs/dev/healthcare/dhis2/lab-results/index.html) series. A laboratory can report a result before the case has been registered in DHIS2, for instance when a facility enters its cases at the end of the day. The lookup by specimen ID then finds nothing, and the result is held until the case exists.

## Holding a result {#holding-a-result}

In `dhis2.lab.write-result`, the branch that handles a missing case stores the request in a [cache](https://zato.io/docs/dev/examples/cache.html) hash under the specimen ID. The key of the hash comes from the `held` section of `dhis2.ini`:

```python
        if case is None:
            cache_key = self.config.dhis2.held.cache_key
            held_request = dumps(request)
            self.cache.hset(cache_key, request.specimen_id, held_request)
            self.response.payload = {'is_found': False}
            return
```

`dumps` is `json.dumps`. The rest of the service is as shown in [Write a result](https://zato.io/docs/dev/healthcare/dhis2/lab-results/write.html#write-the-event). Because the entire request is stored, the retry does not depend on the source the result came from, and HL7 v2 and FHIR results are held and retried in the same way.

## Retrying held results {#retrying-held-results}

A scheduled service reads the hash and invokes `dhis2.lab.write-result` for each held result. A result whose case now exists is written and removed from the hash. A result whose case still does not exist is stored again by the branch above and stays held:

```python
# -*- coding: utf-8 -*-

# stdlib
from json import loads

# Zato
from zato.server.service import Service

class RetryHeldLabResults(Service):
    name = 'dhis2.lab.retry-held'

    def handle(self) -> 'None':

        cache_key = self.config.dhis2.held.cache_key
        held_results = self.cache.hgetall(cache_key)

        for specimen_id, held_request in held_results.items():

            request = loads(held_request)
            response = self.invoke('dhis2.lab.write-result', request)

            # The case exists now and the result was written, so it is no longer held
            if response['is_found']:
                self.cache.hdel(cache_key, specimen_id)
```

The service runs from a [scheduler](https://zato.io/docs/dev/examples/scheduler.html) job with `dhis2.lab.retry-held` as the service and an interval of fifteen minutes.

![Job retrying held results](https://zatosource-production.b-cdn.net/docs/gfx/dhis2/lab-results-held-job-create.webp?v=1791212091)

Dashboard menu: Scheduler > Config

## Next {#next}

[Weekly counts](https://zato.io/docs/dev/healthcare/dhis2/lab-results/weekly.html) reports the number of results per test and outcome to a DHIS2 data set each week.

## See also {#see-also}

- [Write a result](https://zato.io/docs/dev/healthcare/dhis2/lab-results/write.html) - The service the held results are retried through
- [Cache](https://zato.io/docs/dev/examples/cache.html) - Hashes and the other cache operations
- [Scheduler](https://zato.io/docs/dev/examples/scheduler.html) - Interval-based jobs

## Learn more {#learn-more}

- [Healthcare interface engine](https://zato.io/docs/dev/healthcare/) - Clinical messages, FHIR, conversion and operations
- [HL7 v2 parsing](https://zato.io/docs/dev/healthcare/hl7/v2/parsing/) - Messages as typed objects, with field access and validation
- [MLLP channels](https://zato.io/docs/dev/healthcare/hl7v2/mllp/) - Receiving and sending HL7 v2 over MLLP sockets
- [FHIR integrations](https://zato.io/docs/dev/healthcare/hl7/fhir/) - Read and write FHIR resources, with paths, bundles and extensions
- [HL7 v2 to FHIR](https://zato.io/docs/dev/healthcare/hl7/to-fhir/) - Converting v2 messages into FHIR bundles, codes and references included
- [EDIFACT](https://zato.io/docs/dev/healthcare/edifact/) - Parsing interchanges, dialects and the transports they arrive on
- [Transformation](https://zato.io/docs/dev/healthcare/transformation/) - One message in, another standard out, in ordinary Python
- [Audit log](https://zato.io/docs/dev/healthcare/audit-log.html) - Every message with its acknowledgment, searchable by patient identifier
- [AI in clinical interfaces](https://zato.io/docs/dev/healthcare/ai/) - Services calling LLMs and AI agents calling clinical services as tools
