Chapter 2
Design Patterns and API Engineering for Custom Functions
Custom functions are the creative heart of HarperDB extensibility, but true mastery lies in disciplined design and rigorous API craftsmanship. This chapter uncovers advanced patterns and architectures that enable you to build expressive, robust, and future-proof APIs using HarperDB's flexible function ecosystem. By marrying best practices from enterprise web engineering with HarperDB's unique capabilities, you will learn how to architect integrations and interfaces that are as maintainable as they are powerful.
2.1 RESTful Paradigms and Endpoint Design
Within HarperDB's architecture, custom functions serve as programmable interfaces that expose database functionality via RESTful APIs. To harness the full potential of REST principles in these custom functions, one must apply advanced patterns in URI design, resource modeling, and interface semantics while aligning with REST's foundational constraints such as statelessness and idempotency.
Central to RESTful design is the notion of resources as the primary abstraction. Resources should be conceptual entities represented by URIs, not actions or procedural calls. In HarperDB custom functions, this translates into designing endpoint URIs that reflect clear, hierarchical resource paths rather than verb-oriented or RPC-style invocations. For example, an endpoint such as /users/1234/orders cleanly encapsulates the "orders" resource associated with a "user" resource identified by 1234, promoting intuitive navigability and resource discoverability.
URI design should also maintain uniformity and simplicity. Employ nouns predominantly, avoid query parameters to represent resource states or actions beyond filtering and pagination, and leverage plural forms for collections. For instance, /products denotes a collection resource, while /products/567 references a specific product entity. Filtering can be effectively managed with query parameters adherent to conventions like ?status=active, whereas actions that alter resource states belong in the HTTP method semantics rather than the URI path itself.
Statelessness is fundamental to RESTful services and mandates that every request to HarperDB custom function endpoints carry all the information necessary for processing, without relying on server session state. This design ensures scalability and resilience. Authentication tokens, query filters, pagination data, or any modifiers must be conveyed explicitly with each request. Furthermore, HarperDB enforces statelessness by encapsulating function execution contexts fully within the request lifecycle, preventing side effects or contextual dependencies across calls.
Hypermedia as the Engine of Application State (HATEOAS) augments the REST model by embedding hyperlinks within resource representations to guide clients dynamically through possible state transitions. While less common in lightweight HarperDB API implementations, sophisticated endpoints can expose control links within JSON responses, for example:
{ "userId": "1234", "name": "Alice", "links": { "orders": "/users/1234/orders", "update": "/users/1234" } } This hypermedia approach reduces client-server coupling by allowing clients to discover available operations programmatically, greatly facilitating evolvability.
Idempotency is another critical attribute, especially for update and delete operations. HarperDB custom functions should respect the idempotent behavior of HTTP methods: GET, PUT, and DELETE calls should produce the same side effects no matter how many times they are repeated, while POST is reserved for resource creation or non-idempotent commands. For example, invoking PUT /products/567 with the same payload multiple times should yield an identical resultant state without side effects such as duplicate entries or incremented counters.
Consistent interface semantics demand careful adherence to HTTP standards for status codes and headers. Responses must use appropriate codes: 200 OK for successful retrievals, 201 Created for newly created resources, 204 No Content for successful deletions or updates without response bodies, and precise client error codes like 400 Bad Request or 404 Not Found for invalid requests or unknown resources. Content negotiation through Accept and Content-Type headers further standardizes interaction protocols, enhancing interoperability across clients.
Real-world endpoint examples in HarperDB custom functions expose these principles effectively. A typical CRUD interface for managing inventory items might define:
GET /inventory/items # Retrieve list of items GET /inventory/items/789 # Retrieve details for item 789 POST /inventory/items # Create a new item PUT /inventory/items/789 # Update item 789 ...