Skip to content

Commit

Permalink
Merge pull request #1236 from ThorstenHans/feature/enterprise-archite…
Browse files Browse the repository at this point in the history
…ctures-and-patterns

Add enterprise architectures and patterns to the Spin Up Hub
  • Loading branch information
Timothy McCallum authored Apr 5, 2024
2 parents 6feb7cd + 1012709 commit 73c5e59
Show file tree
Hide file tree
Showing 12 changed files with 327 additions and 5 deletions.
27 changes: 27 additions & 0 deletions content/api/hub/architecture_cqrs_go.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
title = "CQRS With Go"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "go", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Go"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A Command and Query Responsibility Segregation (CQRS) implementation in Go"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/cqrs-go"
keywords = "Architecture, HTTP, CQRS"

---

This is a simple Command and Query Responsibility Segregation (CQRS) implementation written in Go.

### What Is Command and Query Responsibility Segregation (CQRS)

CQRS is a software architectural pattern that separates the responsibility of handling commands (requests that change the system's state) from handling queries (requests that fetch data without modifying state). In a CQRS architecture, commands are handled by a separate component or layer known as the Command side, while queries are handled by another component or layer called the Query side. This segregation allows each side to be optimized independently, as they often have different scalability, performance, and optimization requirements.

On the Command side, operations are focused on enforcing business rules, validation, and updating the state of the system. This side typically utilizes a domain-driven design approach to model the business logic effectively. On the Query side, the emphasis is on efficiently retrieving data to fulfill read requests from clients. This side often employs de-normalized data models and specialized data storage mechanisms optimized for fast read access. By separating the concerns of commands and queries, CQRS promotes a clearer separation of concerns and can lead to improved scalability, performance, and maintainability in complex software systems.
27 changes: 27 additions & 0 deletions content/api/hub/architecture_cqrs_rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
title = "CQRS With Rust"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "rust", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A Command and Query Responsibility Segregation (CQRS) implementation in Rust"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/cqrs-rust"
keywords = "Architecture, HTTP, CQRS"

---

This is a simple Command and Query Responsibility Segregation (CQRS) implementation written in Rust.

### What Is Command and Query Responsibility Segregation (CQRS)

CQRS is a software architectural pattern that separates the responsibility of handling commands (requests that change the system's state) from handling queries (requests that fetch data without modifying state). In a CQRS architecture, commands are handled by a separate component or layer known as the Command side, while queries are handled by another component or layer called the Query side. This segregation allows each side to be optimized independently, as they often have different scalability, performance, and optimization requirements.

On the Command side, operations are focused on enforcing business rules, validation, and updating the state of the system. This side typically utilizes a domain-driven design approach to model the business logic effectively. On the Query side, the emphasis is on efficiently retrieving data to fulfill read requests from clients. This side often employs de-normalized data models and specialized data storage mechanisms optimized for fast read access. By separating the concerns of commands and queries, CQRS promotes a clearer separation of concerns and can lead to improved scalability, performance, and maintainability in complex software systems.
38 changes: 38 additions & 0 deletions content/api/hub/architecture_crud_go_sqlite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
title = "CRUD APIs With Go and SQLite"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "Go", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Go"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A full-fledged CRUD API with SQLite backend written in Go"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/http-crud-go-sqlite"
keywords = "Architecture, HTTP, CRUD"

---

This is a sample implementation of CRUD (Create, Read, Update, Delete) in Go. The sample is using SQLite for persistence and provides the following API endpoints via HTTP:

- `GET /items` - To retrieve a list of all items
- `GET /items/:id` - To retrieve a item using its identifier
- `POST /items` - To create a new item
- `PUT /items/:id` - To update an existing item using its identifier
- `DELETE /items` - To delete multiple items providing an array of identifiers as payload (`{ "ids": []}`)
- `DELETE /items/:id` - To delete an existing item using its identifier

Send data to `POST /items` and `PUT /items/:id` using the following structure:

```jsonc
{
"name": "item name",
// boolean (either true or false)
"active": true
}
```
38 changes: 38 additions & 0 deletions content/api/hub/architecture_crud_js_pg.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
title = "CRUD APIs with JavaScript and PostgreSQL"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "JavaScript", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "JS/TS"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A full-fledged CRUD API with PostgreSQL backend written in JavaScript"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/http-crud-js-pg"
keywords = "Architecture, HTTP, CRUD"

---

This is a sample implementation of CRUD (Create, Read, Update, Delete) in JavaScript. The sample is using PostgreSQL for persistence and provides the following API endpoints via HTTP:

- `GET /items` - To retrieve a list of all items
- `GET /items/:id` - To retrieve a item using its identifier
- `POST /items` - To create a new item
- `PUT /items/:id` - To update an existing item using its identifier
- `DELETE /items` - To delete multiple items providing an array of identifiers as payload (`{ "ids": []}`)
- `DELETE /items/:id` - To delete an existing item using its identifier

Send data to `POST /items` and `PUT /items/:id` using the following structure:

```jsonc
{
"name": "item name",
// boolean (either true or false)
"active": true
}
```
38 changes: 38 additions & 0 deletions content/api/hub/architecture_crud_js_sqlite.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
title = "CRUD APIs with JavaScript and SQLite"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "JavaScript", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "JS/TS"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A full-fledged CRUD API with SQLite backend written in JavaScript"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/http-crud-js-sqlite"
keywords = "Architecture, HTTP, CRUD"

---

This is a sample implementation of CRUD (Create, Read, Update, Delete) in JavaScript. The sample is using SQLite for persistence and provides the following API endpoints via HTTP:

- `GET /items` - To retrieve a list of all items
- `GET /items/:id` - To retrieve a item using its identifier
- `POST /items` - To create a new item
- `PUT /items/:id` - To update an existing item using its identifier
- `DELETE /items` - To delete multiple items providing an array of identifiers as payload (`{ "ids": []}`)
- `DELETE /items/:id` - To delete an existing item using its identifier

Send data to `POST /items` and `PUT /items/:id` using the following structure:

```jsonc
{
"name": "item name",
// boolean (either true or false)
"active": true
}
```
26 changes: 26 additions & 0 deletions content/api/hub/architecture_pub_sub.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
title = "Polyglot Publish-Subscribe"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["publish-subscribe", "architecture", "polyglot"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Polyglot"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "Publish-Subscribe implementation using multiple programming languages (Rust, Go, JavaScript)"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/pub-sub-polyglot"
keywords = "Architecture"

---
This sample contains a Publish-Subscribe (sometimes referred to as _pub/sub_) pattern implemented using different programming languages.

### What is Publish-Subscribe

The Publish-Subscribe pattern is a messaging pattern widely used in distributed systems to facilitate communication between multiple components or modules in a decoupled manner. In this pattern, publishers are responsible for producing messages containing data or events of interest, while subscribers express interest in specific types of messages by subscribing to relevant topics or channels. When a publisher generates a message, it is broadcasted to all subscribed subscribers without the publisher needing to have any knowledge of the subscribers' identities or how they process the messages. This decoupling enables loose coupling between components, making systems more flexible, scalable, and easier to maintain.

Subscribers can react to messages they are interested in by executing predefined actions or processing the data contained within the messages. This pattern is commonly implemented using message brokers or event buses, where publishers send messages to a centralized location and subscribers receive messages from this central hub. By leveraging Publish-Subscribe, you can design systems where components are highly modular and can be easily extended or modified without affecting other parts of the system. Additionally, this pattern supports asynchronous communication, enabling efficient handling of large volumes of messages and improving system responsiveness.
27 changes: 27 additions & 0 deletions content/api/hub/architecture_signed_webhooks.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
title = "Signed Webhooks"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["webhooks", "rust", "python", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "An implementation of signed webhooks using the WebAssembly Component Model."
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/signed-webhooks"
keywords = "Architecture, HTTP, webhooks"

---

This sample demonstrates how to implement signed webhooks by extracting signing and verification logic into a dedicated WebAssembly Component and re-using it from within WebAssembly Components written in different programming languages.

### What Are Signed Webhooks?

Webhooks are automated messages sent from one application to another when a specific event occurs. They enable real-time communication and trigger actions in response to events, eliminating the need for continuous polling.

Signing the payload of webhooks is crucial for ensuring the integrity and authenticity of the data being transmitted between applications. By signing the payload, you can verify that the data received from a webhook hasn't been tampered with during transit and originates from a trusted source. This security measure helps prevent various forms of attacks, such as data tampering or injection, which could potentially compromise the integrity and reliability of the system.
25 changes: 25 additions & 0 deletions content/api/hub/architecture_transparent_cache_rust.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
title = "Transparent Cache with Rust"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "key-value", "rust", "architecture"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Architecture"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "A transparent cache implementation using key-value store"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/caching-rust"
keywords = "Architecture, HTTP"

---

This example illustrates how to implement caching when building HTTP APIs.

### What Is a Transparent Cache

A transparent cache is a caching mechanism that operates without the explicit involvement or awareness of the end user or client application. In other words, users interacting with a system are unaware that caching is taking place behind the scenes. From the perspective of the user or client application, the caching process is invisible and does not impact the functionality or behavior of the system. Transparent caching is commonly employed in systems where performance optimization is crucial, such as web applications or content delivery networks (CDNs), to reduce latency and server load without affecting user experience.
27 changes: 27 additions & 0 deletions content/api/hub/pattern_content_negotiation.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
title = "Content Negotiation"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "rust", "patterns"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Pattern"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "Illustrates how to add content negotiation to your Spin Apps"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/content-negotiation-rust"
keywords = "Patterns, HTTP"

---

This Spin App illustrates how to implement content negotiation in Rust

### What Is Content Negotiation

Content negotiation is a crucial concept in API development that allows clients and servers to agree on the format and structure of exchanged data. It enables interoperability between different systems by enabling them to communicate using various data formats, such as JSON, XML, or even HTML. Typically, content negotiation occurs during the HTTP request process, where the client expresses its preferences for the data format through request headers like 'Accept'. The server then examines these preferences and selects the most suitable representation of the requested resource, taking into account factors like available formats and the client's stated preferences.

Implementing content negotiation ensures that your APIs can cater to a diverse range of clients with varying capabilities and preferences. By supporting multiple data formats, you can reach a broader audience and accommodate different client needs without requiring separate endpoints for each format. Additionally, content negotiation promotes flexibility and future-proofing, as it allows you to introduce new data formats or modify existing ones without impacting clients that support different formats. Properly implemented content negotiation enhances the usability and accessibility of APIs, fostering seamless communication between clients and servers.
27 changes: 27 additions & 0 deletions content/api/hub/pattern_cors.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
title = "CORS (Cross-Origin Resource Sharing)"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/plain"
tags = ["http", "rust", "patterns"]

[extra]
author = "Thorsten Hans"
type = "hub_document"
category = "Pattern"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "Illustrates how to implement CORS (Cross-Origin Resource Sharing) in Rust"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/cors-rust"
keywords = "Patterns, HTTP, CORS"

---

This Spin App illustrates how to implement CORS (Cross-Origin Resource Sharing) in Rust

### What Is Cross-Origin Resource Sharing (CORS)?

CORS, or Cross-Origin Resource Sharing, is a security mechanism implemented by web browsers to control access to resources located on different domains. As an API developer, understanding CORS is crucial when building web APIs that need to be accessed by client-side scripts from web browsers. CORS prevents a web page from making requests to a different domain than the one that served the page, known as the same-origin policy, unless explicitly permitted. This restriction helps mitigate certain types of cross-site scripting (XSS) attacks.

To enable cross-origin requests, you need to configure their servers to include specific HTTP headers in their responses. These headers, such as `Access-Control-Allow-Origin`, indicate which domains are allowed to access the API's resources. By setting appropriate CORS headers, you can define the level of access permitted, whether it's open to all origins (`*`) or limited to specific domains. Additionally, you should be aware that preflight requests may be sent by the browser for certain types of requests, such as those with custom headers or methods, and they need to handle these preflight requests appropriately to ensure seamless communication between client-side scripts and the API.
22 changes: 22 additions & 0 deletions content/api/hub/sample_load_testing_spin_apps_with_k6.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
title = "Load-Testing Spin Apps with Grafana k6"
template = "render_hub_content_body"
date = "2024-04-03T13:50:00Z"
content-type = "text/html"
tags = ["Rust", "Load-Testing"]

[extra]
author = "ThorstenHans"
type = "hub_document"
category = "Sample"
language = "Rust"
created_at = "2024-04-03T13:50:00Z"
last_updated = "2024-04-03T13:50:00Z"
spin_version = ">=v2.4.0"
summary = "This sample demonstrates how one could perform load-testing for Spin Apps with Grafana k6"
url = "https://github.com/fermyon/enterprise-architectures-and-patterns/tree/main/load-testing-spin-with-k6"

---

Grafana [k6](https://k6.io/) is an open-source load testing tool that makes performance testing easy and productive for engineering teams. k6 is free, developer-centric, and extensible.

This sample illustrates how to load-test your Spin Apps.
10 changes: 5 additions & 5 deletions spin-up-hub/src/store.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,8 @@ const store = createStore({
tags: [], language: "", createdAt: "", lastUpdated: "", spinVersion: "",
artifactSource: ""
},
contentTypes: ["Plugin", "Template", "Library", "Sample", "Component"],
languages: ["Rust", "JS/TS", "Go", "Python"],
contentTypes: ["Plugin", "Template", "Library", "Sample", "Component", "Pattern", "Architecture"],
languages: ["Rust", "JS/TS", "Go", "Python", "Polyglot"],
contentFilters: [],
languageFilters: [],
contentItems: [],
Expand Down Expand Up @@ -124,11 +124,11 @@ const store = createStore({
this.field('content')
this.field('language', { boost: 10 })
this.field('author'),
this.field('tags', { boost: 10 })
this.field('tags', { boost: 10 })
this.field('keywords', { boost: 10 })
this.field('url')
this.ref('id')

documents.forEach(function (doc) {
this.add(doc)
}, this)
Expand Down Expand Up @@ -157,4 +157,4 @@ function formatTimestamp(timestamp) {
return new Date(timestamp).toLocaleDateString('en-US', options);
}

export { store, unescapeHTML }
export { store, unescapeHTML }

0 comments on commit 73c5e59

Please sign in to comment.