-
Notifications
You must be signed in to change notification settings - Fork 0
Concierge Service Goals
This page outlines the development principles that guide Concierge's growth as it adds more suppliers and serve a large number of requests.
Because of its nature, Concierge interacts a lot of external services - supplier APIs. Due to the nature of such communications, many things can go wrong during the process - network failures, unstable supplier services, crashes on external services, bugs and invalid responses. The list can get pretty long.
However, such external failures should not compromise Concierge's service. In more practical terms, if an exception happens at the supplier service and the response does not correspond to a successful response expectation, Concierge should not crash. Instead, an error HTTP response should be returned to the caller, with a descriptive error message. The external error can be logged and further analysed later.
Examples of external failures that cannot cause Concierge to fail:
- Concierge cannot connect to the supplier's servers.
- The request times out.
- The supplier's API returns a non-successful HTTP status.
- The supplier's API was supposed to return JSON, but returned XML instead.
- The supplier's API returns a response that does not conform to the expected format (a required value is not present.)
- Concierge's database is unavailable.
See the implementation and usage of the Result
class for an idea on how to handle error scenarios.
Also, with regards to the last point above, it is important to notice that Concierge does not require a database to function. While having a working database provides extra functionality - such as caching and metadata tracking - that should not be required for Concierge to perform its operations. Therefore, all operations should succeed even in the scenario where the database is temporarily unavailable. Concierge provides a Concierge::OptionalDatabaseAccess
facility for that purpose. Check the class documentation for usage instructions.
Concierge uses the Hanami framework. Even though it's still in a very early stage, its architecture is good and encourages a more modular design. Concierge fully embraces that principle.
Tips for developing new features or integrations on Concierge:
- If a class is doing too much, separate the work into smaller, more focused classes.
- Prefer composition over inheritance. Unless it's extremely natural to use inheritance, be wary of it. If the only intent is to provide some functionality to different classes, composition is a much better approach.
- Make sure all classes have good test coverage.
- Include tests that exercise the full stack. In case of the Concierge API, these would be controller tests.
Concierge should respond as quickly as possible. Oftentimes, the bottleneck of some API calls are the supplier APIs response time - that should be the only bottleneck. Be wary of performing any other blocking IO during a request lifecycle, especially when the operation is not required for the response to be returned to the client.
Such blocking calls might unnecessarily compromise the client's response and could be tackled in the background, by a job processor.
It is not uncommon that suppliers will have quirks and behaviours that are specific to them. This kind of knowledge must be documented. At least two forms of documentation must exist, for each supplier:
- source-code level documentation: this includes comments in the client classes. Documentation here is mostly focused on implementation details, usage examples, etc.
- Wiki entries: for every supplier, there must be an entry in the project Wiki describing the supplier, its API. This should point to an official documentation, if any, as well as an overall description on how to perform each Concierge operation with that supplier: quotations, placement and cancellation of reservations, and so on.