From b20c5312edc0cb292b3f98ff0b3e19339dc856d5 Mon Sep 17 00:00:00 2001 From: Jonathan Joyce Date: Mon, 24 Jun 2024 20:37:47 -0600 Subject: [PATCH] Documentation updates and refinement --- docs/architecture/infrastructure.md | 2 +- docs/ingest/events.md | 12 ++++++++---- docs/ingest/ingest-prototype.md | 6 +++--- docs/ingest/ingest.md | 7 ++++--- docs/ingest/kerchunk.md | 20 ++++++++++++++++++++ docs/ingest/lambda-workflow.png | Bin 0 -> 29096 bytes 6 files changed, 36 insertions(+), 11 deletions(-) create mode 100644 docs/ingest/kerchunk.md create mode 100644 docs/ingest/lambda-workflow.png diff --git a/docs/architecture/infrastructure.md b/docs/architecture/infrastructure.md index d1349c8..96a2547 100644 --- a/docs/architecture/infrastructure.md +++ b/docs/architecture/infrastructure.md @@ -1,7 +1,7 @@ --- layout: default title: Infrastructure -nav_order: 3 +nav_order: 2 has_children: true --- diff --git a/docs/ingest/events.md b/docs/ingest/events.md index e777c27..9e4e130 100644 --- a/docs/ingest/events.md +++ b/docs/ingest/events.md @@ -1,7 +1,7 @@ --- layout: default parent: Data Ingest -nav_order: 3 +nav_order: 4 --- # Event Messaging @@ -9,7 +9,7 @@ nav_order: 3 Event messaging allows the system to respond and operate in near real-time while supporting scalability and extensibility for future use-cases. Designing around a messaging system provides a centralized mechanism for system components to communicate without coupling those components. That means new components to be added to the system ad-hoc and without redesigning core capabilities. Event-driven systems are able to scale by sending messages to many listeners at once. They also tend to distribute data through the system faster than batch systems because the event is raised immediately versus waiting a set increment of time. **Key Points** -- An event is any change in data state, fundamentally new available data +- An event is any change in data state, i.e. fundamentally new available data (new, updated, and deleted) - Event systems make extending the system easier as requirements evolve - Event-driven design results in data propagating through the system faster than traditional scheduled batch systems @@ -25,6 +25,10 @@ We have prototyped messaging using SNS because we are able to receive messages d ## RabbitMq -There are many modern messaging frameworks to choose from today. Every cloud platform provides their own brand of messaging (Amazon Simple Queue Service (SQS), Google Pub/Sub, and Azure Service Bus) and there are numerous open-source platforms as well. We initially prototyped RabbitMq as the messaging broker because it is relatively simple to configure, open source, and cloud platform independent. From a system architecture perspective, the main difference between SQS and RabbitMq is that SQS only works on AWS while RabbitMq will work on whatever platform it is installed on. However, SQS is already configured and "comes with" AWS natively. +There are many modern messaging frameworks to choose from today. Every cloud platform provides their own brand of messaging (Amazon Simple Queue Service (SQS), Google Pub/Sub, and Azure Service Bus) and there are numerous open-source platforms as well. We initially prototyped RabbitMq as the messaging broker because it is relatively simple to configure, open source, and cloud platform independent. -> RabbitMQ is the most widely deployed open source message broker. RabbitMQ is lightweight and easy to deploy on premises and in the cloud. It supports multiple messaging protocols. (https://www.rabbitmq.com/) \ No newline at end of file +> RabbitMQ is the most widely deployed open source message broker. RabbitMQ is lightweight and easy to deploy on premises and in the cloud. It supports multiple messaging protocols. (https://www.rabbitmq.com/) + +## Comparison + +From a system architecture perspective, the main difference between SQS and RabbitMq is that SQS only works on AWS while RabbitMq will work on whatever platform it is installed on. However, SQS is already configured and "comes with" AWS natively. This is not really a limitation because if and when IOOS has the need to connect to other cloud providers (e.g. GCP, Azure), those new integrations can be developed without a major change to the underlying technical strategy. All of the major cloud providers support a messaging framework so there is no technical limitation, but each additional supported platform requires additional developer support and maintenance. On the other hand, using consistent tooling among cloud providers reduces the number of configurations and therefore platform-specific test-cases to be addressed. One could also argue that the maintenance and understanding of the RabbitMq system is another hidden developer cost that is not an issue in the managed services such as AWS SQS which is [maintained by Amazon 24/7](https://docs.aws.amazon.com/wellarchitected/latest/reliability-pillar/example-implementations-for-availability-goals.html) and just works. diff --git a/docs/ingest/ingest-prototype.md b/docs/ingest/ingest-prototype.md index 1667dc2..aced6bc 100644 --- a/docs/ingest/ingest-prototype.md +++ b/docs/ingest/ingest-prototype.md @@ -1,11 +1,11 @@ --- layout: default -title: Prototype +title: Kerchunk Workflow (Argo/K8s) parent: Data Ingest -nav_order: 1 +nav_order: 2 --- -# Data Ingest Prototype +# Argo Kerchunk Workflow ![Prototype Diagram](modeldata-prototype-diagram.png) diff --git a/docs/ingest/ingest.md b/docs/ingest/ingest.md index 45ed8fa..e54ba71 100644 --- a/docs/ingest/ingest.md +++ b/docs/ingest/ingest.md @@ -1,7 +1,7 @@ --- layout: default title: Data Ingest -nav_order: 2 +nav_order: 3 has_children: true --- @@ -13,9 +13,10 @@ Data Ingest starts the process of preparing data for transformation and notifyin - The system needs a method of incorporating raw data in order to provide more value to that data. - *Raw data* referred to here may be a traditional GRIB or NETCDF file, but could also be video or imagery. - The raw data does not necessarily need to be copied to be ingested; if data is already cloud accessible it still needs to be ingested but not copied. -- Data needs to pass quality control checks. Bad data in causes bad data analysis, and in the case of AI/ML, potentially invalid models. +- Data needs to pass quality control checks. Bad data inputs corrupt good data analysis. + - Using bad data to train AI/ML models wastes effort because it will likely produce inaccurate results. - The metadata needs to be extracted from the raw data files to feed the larger system. -- The system does not enforce raw data standards. If a data product requires reformatting or rechunking then it's the responsibility of that product subdomain to provide that product. +- The system requires that the data is indexable by byte-range requests. Common scientific formats such as GRIB and NetCDF adhere to this requirement and are easily indexed using the [kerchunk process](ingest-prototype.md). - This process needs to be constantly monitored. A dedicated data team should be responsible for data ingest in operations. ## Data Ingest Concepts diff --git a/docs/ingest/kerchunk.md b/docs/ingest/kerchunk.md new file mode 100644 index 0000000..646d741 --- /dev/null +++ b/docs/ingest/kerchunk.md @@ -0,0 +1,20 @@ +--- +layout: default +title: Kerchunk Workflow (RPS/Lambda) +parent: Data Ingest +nav_order: 1 +--- + +# Lambda Kerchunk Workflow + +![Prototype Diagram](lambda-workflow.png) + +[Source Code and Technical Documentation](https://github.com/asascience-open/nextgen-dmac/tree/main/cloud_aggregator) + +The data ingest prototype starts by listening to events from the NODD bucket when new files are added. This kicks off an SNS notification, which is then queued in SQS. The reason for doing this is so that all messages can be received and read even if there might not be a listener ready exactly when the notification is generated. + +The Lambda functions are triggered when new messages arrive in the SQS queue. A Lambda function creates a temporary virtual machine running the Docker image we built, which executes our custom Python code. This Python code kerchunks the appropriate files and then writes the index zarr files to the destination S3 bucket. + +The kerchunked data is written to the public Cloud--Optimized DMAC bucket. Note that the kerchunked data is a reference to the NODD data, not a copy, so the NODD data must remain available for the kerchunk reference to work. + +The same listener pattern is applied to the destination bucket: when new files are added, it generates events that go into a queue, and the `aggregation` Lambda kicks off a workflow to produce the "best forecast" kerchunk for the available data, and the entire model run (1 cycle) as one reference file. \ No newline at end of file diff --git a/docs/ingest/lambda-workflow.png b/docs/ingest/lambda-workflow.png new file mode 100644 index 0000000000000000000000000000000000000000..fdaf4e60fd66b5e4f4bda6340be03a980077c3ba GIT binary patch literal 29096 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