My domain requires that a Resource
(ubiquitous language for a singular unit of data to be moved - commonly a file or folder) can only be moved if it has been Scanned
to ensure it does not contain any Threats
. Resources
are moved from a Lowside
MountedDrive
(essentially some external filesystem, as far as I know a lowside is just the hostname of a machine, and the mounted drive contains base path information) to 1 or more Highside
data repos. The entity that encapsulates this is called an Ingest
Implementation will involve the usage of multiple antivirus softwares and a custom written content check. It is obvious that implementation of the adapters for the antivirus software must be in the infrastructure layer. I am not so certain for the custom written content check though.
My learning so far indicates to me that the process of a scan does not belong to a domain entity, so it is a domain concern. So I believe this is a prime example of a domain service. These scans may take a long time, far too long to be waited on synchronously.
- how can I design my
IResourceScanner
to be run asynchronously without being a leaky abstraction? - Should this
Scanner
scan theIngest
that contains the resources that need to be scanned or be independent of theIngest
public interface IResourceScannerService {
void StartScan(Resource r, Lowside l, MountedDrive m);
}
// or
public interface IIngestScannerService {
void StartScan(Ingest i);
}
Neither doesn't seem to tell what it does from the interface. In addition, it would be hard to know that you need to update properties on the resource and persist them for it to be recognized as scanned. Perhaps this is a use case for domain events but I am honestly unsure. You also cannot cancel a running scan with this. This entire thing eludes me.
It's hard to know how to use this without knowing how to run it as a background process that is non-blocking. There are 2 possible things that make sense to me;
// Directly in the entity
class Ingest : ... {
public void ScanResources(IResourceScannerService scanner) {
// Queues all the scans for its resources.
}
}
// In a use case
class ScanIngestUseCase {
private IIngestScannerService scanner
public ScanIngestUseCase(IIngestScannerService s) {
scanner = s
}
void execute(int ingest_id) {
ingest = // get the ingest from repo
s.StartScan(ingest)
}
}
In addition, what would be the natural way to actually access and manipulate the Resource
, given we only have a Lowside
and MountedDrive
? I'm thinking that accessing the resources is not a domain issue - it is an implementation detail of the scanning and transfer logic which exists in the domain layer. Thus perhaps a simple TerminalClient
factory like;
public class TerminalClientFactory {
ITerminalClient create(string connection_string) {
...
}
}
that exists purely in the infrastructure layer would be appropriate. It is a requirement that we have a commandline of sorts to operate on. This raises the question; how do I handle all the kinds of terminals? My requirements luckily only require I support Ubuntu, but for curiousity sake what if I wanted to also support Windows, Centos, etc?