Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added adr-0102-phoenix-multiple-language-support #208

Draft
wants to merge 9 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
29 changes: 29 additions & 0 deletions docs/overview/design/arch-decision-records/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Architectural Decision Record (ADR)

Write down key architecture design decisions along with the context and implications of the decision. Each decision record should describe a single decision. What makes a decision architectural and not simply detailed design is subjective, but here are some features of an architectural decision:

- It affects another component or team
- The decision affects how the system influences on or more quality attributes, for better or worse
- The decision was precipitated by a business or technical constraint
- The decision has far-reaching, significant impact such as framework or technology choice
- The decision fundamentally changes the way the team develops or ships the system

## Guidelines

- Include only one decision per file
- Sequentially number ADRs and keep old records. Add references to old records when a decision is superseded or changed.
- Keep ADRs short, one or two pages at most.
- Use plain language when recording decisions.
- Put architecture decisions through the same review process as code.
- Store in version control
- Augment with other architecture documentation

## Statuses

Draft, Proposed, Accepted, Superseded, or Deprecated

Additionally, Retroactive will be used for a decision that was made far in the past, and we're merely documenting it

## Acknowledgements

Credit to Michael Keeling for much of the text in this README
31 changes: 31 additions & 0 deletions docs/overview/design/arch-decision-records/adr-0000-adr-process.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# ADR-0000 - Establish ADR Process

## Context

Over the past year, the Aerie project team has been tasked by its primary sponsor, the NASA AMMOS program, to incorporate enhanced spacecraft sequencing capabilities into Aerie (this task has been colloquially called SEQ 2.0). The program is interested in ensuring sufficient oversight to preserve stakeholder buy-in on the task as it progresses. In addition, new organizations are contributing to the project (e.g. Goddard Spaceflight Center, Ames Research Center) that have less familiarly with the Aerie project and its history. These drivers have created an increased need to clearly communicate architectural decisions and their rationale.

## Decision

Create an architectural decision record and use it to track architectural decisions. This record will live alongside the rest of the project's documentation in a separate section.

Identifiers for new decisions made after the establishment of this process will begin at 0100 and will tick upward monotonically (numbers below 0100 will be used to document historical decisions the project feels are worth communicating to future contributors). ADRs will be loosely chronological, but are not required to be. If we find the need to document a past decision, it's fine to allocate it the next available number.

A basic template and readme will be available to create new ADRs and briefly describe the content that should be within a record.

## Alternatives Considered

We could use the GitHub PR and issue history to track these decisions, but it can be difficult to traverse those. GitHub Discussions are also a viable home for these records, but that precludes offline editing, and isn't particularly dense or organized. Remaining in GitHub as opposed to documenting these decisions in a different location is preferred to keep these decisions close to the code that ultimately reflects these decisions.

## Consequences

### Positive

- The project will have a clear written record that explains where we are today and how we got here, which currently does not exist
- Records will be tracked in the main repository alongside the source code so that architectural decisions are transparent to the project community and can be authored, reviewed, and approved by community members
- ADR reviews can serve as an opportunity for project stakeholders and sponsors to provide feedback on the direction of the project
- There is a lower barrier of entry to get involved in the projects design process since it can be seen by all members of the community

### Potential Negative

- If not kept up to date, these documents may become misleading and actually be more hurtful than helpful.
- Writing and reviewing these documents will take time on an already resource constrained team
29 changes: 29 additions & 0 deletions docs/overview/design/arch-decision-records/adr-0001-java.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# ADR-0001 - Java as a mission modeling language

## Context

APGen, Aerie's predecessor, used a Domain-Specific Language (DSL) for defining activities and resources.

From a paper on Blackbird (see [References](#references)), a key source of inspiration for the Aerie project:

> Much of Blackbird’s ease of use derives directly from how adapters write code directly in an industry-standard programming language. Features such as an integrated development environment (IDE) with debugging, static code analysis, performance profiling, ease of calling external libraries, online reference resources, native test frameworks, formal dependency management, and more have all reduced development time and uncaught errors. Java has been GitHub’s second most-used language since 2013 [13] and the first most-used on the TIOBE index since 2015 [14], so new developers may already be familiar with it, and all adapters benefit from an active community and helpful resources. To create an activity in Blackbird, only a small subset of the full Java language is required, so even new adapters can make contributions quickly, then add more complex behavior as their proficiency grows. Blackbird adapters typically become proficient in about two weeks full-time. Blackbird adaptations listed in later sections all required people working only part-time for limited commitments, whereas traditionally missions need to dedicate at least one full-time person for years. If a project decides that they want to use another language to write their activities, they can seamlessly incorporate Python-like Groovy, JavaScript-like Kotlin, or Lisp-like Clojure, which can all inherit Blackbird’s Java base classes. Groovy and Kotlin proofs of concept were built which motivated multiple projects using Blackbird to consider partially switching to one of these other languages to further improve the new adapter experience. Based on experience training more than 10 people to use Blackbird, the largest impediments to ease of use are not the language syntax, but the use of an IDE for adapters without prior experience, and understanding when their adaptation code will execute as part of the simulation. One is not forced to use an IDE to develop in Blackbird, but the initial investment to learn to use one is often worth the reduced risk and improved productivity afterwards. Stepping through code in the debugger has greatly helped adapters understand when their code will be called, which will always be non-trivial for any complex system. There is a detailed adapter’s guide which walks new users through defining and deploying an adaptation.

13. "Projects", The State of the Octoverse, [online] Available: https://octoverse.github.com/projects.html
14. TIOBE Index, [online] Available: https://www.tiobe.com/tiobe-index/.

## Decision

Based on much of the same rationale provided by Blackbird, we choose to use Java as the language that users will use to define mission models

## Alternatives considered

Python is another very popular language within the aerospace and scientific communities. When providing demonstrations of Aerie's Java mission modeling language to various organizations, there have been many requests for a Python framework in addition or in lieu of a Java on. Adding or replacing the Java mission model framework with a Python one would likely help product adoption. However, there are technical challenges to hosting Python. It has a history of breaking changes, and has no notion of an "interface". It is not designed for multi-tenancy, has no JIT-compiler, and has a largely architecture-specific ecosystem (e.g. key python libraries are often written in C to improve performance and cannot easily be ported between different compute architectures). We also felt strongly that the mission model should be written in the same language as the simulator itself, and Python was not considered an appropriate implementation language for the performance-critical or complex parts of the application.

## Consequences

- Missions have been able to push Java quite far, pulling in frameworks like Guava, and Dagger.
- Potentially lower adoption rates from mission users whose personnel and ground systems are primarily built on python

## References

- C. R. Lawler, F. L. Ridenhour, S. A. Khan, N. M. Rossomando and A. Rothstein-Dowden, "Blackbird: Object-Oriented Planning, Simulation, and Sequencing Framework Used by Multiple Missions," 2020 IEEE Aerospace Conference, Big Sky, MT, USA, 2020, pp. 1-20, doi: 10.1109/AERO47225.2020.9172680.
157 changes: 157 additions & 0 deletions docs/overview/design/arch-decision-records/adr-0002-graphql.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
# ADR-0002 - GraphQL instead of REST API

NOTE: Apollo has been replaced by Hasura as of [0003-hasura-and-postgres](../adr-0003-hasura-and-postgres).

## Context

#### Aerie API Needs

1. Evolve the internal APIs rapidly and the public APIs slowly.

The development of the Aerie user interface and application
internal components proceeds in parallel. As a result, the user
interface’s data needs imposes constraints on the definition of the
system’s public API. The evolving nature of the user interface’s
development makes it difficult to carry out an API design effort,
as would be the case for a REST API architectural style. Further,
the structure of resources needed by the highly configurable
interface components within the user interface, makes defining an
efficient set of resource endpoints prohibitively difficult. Such
endpoints would require continuous editing and updating as
development progressed.

2. Multiple clients and multiple different workflows for clients.

There exists a category of use cases in which customers develop
custom Aerie client applications. Such customization requires the
flexibility to easily define new data projections as simple queries
constructed by a client. As a result, Aerie benefits from an API
that supports high query flexibility from both the external client

3. Ability to dynamically reduce/transform response payloads.

Within the planning, scheduling and sequencing domain are a number
of common list like data structures/concepts which are often quite
large in size (number of elements). It is inefficient to impose
upon any client seeking a particular view/aspect of the data
structure to request and process the entire structure. For example,
certain resources can’t be made "smaller" without compromising
their intent. A Plan can be filtered but not sensibly
partitioned. It is desirable that any client requesting such data
structures be provided with an easily accessible means to query the
data structure for the elements/projection of interest.

4. Custom queries and batch fetching.

The Aerie stores a number of significant mission data sources
(E.g. activity plan, simulation results, and constraint violation
results). Aerie must provide users flexible access to this data to
support an arbitrary space of use cases for reporting, auditing and
interfacing with third-party customers.

#### Trade Study

A trade study was conducted to evaluate available API products. A down selection of the tools left both the [Tyk API](https://tyk.io/) gateway product and [Apollo GraphQL Server](https://www.apollographql.com/) product. The primary difference between these two products are their approach to exposing data. The Tyk gateway exposes system queries as [Representational State Transfer(REST)](https://www.codecademy.com/article/what-is-rest) endpoints while the Apollo GraphQL server exposes a single GraphQL query endpoint. The REST and GraphQL architectural styles present different approaches and embody contrasting capabilities. Representational State Transfer is an architectural style for distributed hypermedia systems. GraphQL is a query language for an API, exposed as a typed schema defined by a data graph. Table 3 presents a set of desirable API properties and the manifestation of each property for REST and GraphQL driven APIs.

Table 3 Comparison of REST and GraphQL capabilities

| System Property | REST | GraphQL |
| -------------------------------------------------- | ------- | ------------------ |
| Modifiability | ✅ | Runtime inspection |
| Scalability | ✅ | ❌ |
| Portability | ✅ | ✅ |
| Reliability | ✅ | ✅ |
| Simplicity | ✅ | ✅ |
| Visibility | ✅ | ✅ |
| Performance | ✅ | ❌ |
| Discovery and Introspection | Limited | ✅ |
| Consistency | ❌ | ✅ |
| Ease of Server Development | ❌ | ✅ |
| Ease of Client Development | ❌ | ✅ |
| Over-fetching protection without proper API design | ❌ | ✅ |
| Active Community | ✅ | ✅ |
| Tooling Server | ✅ | ✅ |
| Tooling Client | ✅ | ✅ |
| Tooling API Management | Limited | ❌ |
| Maturity | ✅ | ❌ |
| Works with any data representation | ✅ | ❌ |
| Printed Books | ✅ | ✅ |
| Enterprise Ready | ✅ | ✅ |

The following is a discussion of the particular API qualities which
provide for Aerie’s needs.

- **Discovery and Introspection** - The GraphQL data graph schema
provides a contract-like mechanism where requests and replies are
inherently typed and can be directly validated and resolved based on
those types. This contract like nature completely describes all
possible requests/responses where a typed service provider won’t
compile until it fully implements its contract. A typed service
consumer will be type-checked at compile time, which helps to catch
problems before deployment. Finally, it is unreasonable to expect
that a well-performant API can be developed for every conceivable
use case. As a result the improved introspection at the per field
level in GraphQL allows for targeted optimization of common or slow
queries.

- **Consistency** - The API schema is typed and therefore either
correct or not. As a result, there is an inherent consistency
between client and server because both must abide by the generated
schema.

- **Ease of Server Development** - It is easier (development time,
complexity) to develop and maintain data source resolvers as part of
a GraphQL server. Well designed, true REST APIs take time and
resources and are therefore more difficult to design and
maintain. GraphQL relieves the project of that unnecessary burden.

- **Ease of Client Development** - A client can develop against the
exposed contract. A client can develop custom queries targeted to
its own use cases to limit both over and under fetching. In many
cases this may reduce latency and increase performance by limiting
client side data manipulation/filtering.

- **Flexibility of API Design** - User and mission needs are
constantly evolving. GraphQL decouples the API allowing the Aerie
team to make adjustments to the API according to evolving customer
needs. Additionally, the increased granularity and visibility when
auditing the frequency and combinations with which certain fields
are queried, allows for clearly validated deprecation, removal, and
changes of fields available in the API schema.

## Decision

Use Apollo GraphQL. (Later, [[0003-hasura-and-postgres]])

The Aerie GraphQL API presents a consistent application boundary to Aerie users. The API server enables the composition of multiple APIs (internal to the application) as a single API endpoint. The API component additionally provides a location in the system for the following needs:

- Manipulation of data
- Response Caching

## Consequences

By adopting GraphQL we knowingly forgo certain
capabilities/constraints of a REST API. Three cases have been
identified as possible risks and sufficient mitigation options are
identified:

1. **Tooling API Management** - GraphQL is a newer technological approach to APIs (2012).
**Mitigation:** Aerie has chosen to use Hasura, a major open source contributor to the GraphQL community.
2. **Caching** - REST over HTTP benefits from existing HTTP server caching and browsers client caching mechanisms.
**Mitigation:** Most GraphQL libraries have caching mechanisms built in. Hasura caching must be handled with annotations/directives on the graph definition.
3. **Client-API Loose Coupling** - Each new client application must make affordance at development time and hardcode custom queries and mutations as made possible by the Aerie GraphQL schema.
**Mitigation:** None. In the Aerie context this is not considered a benefit.

## Retrospective

Note, since the time of this original decision, the loose coupling of the client API provided by GraphQL has resulted in some challenges for missions using or considering to use Aerie:

- While missions have full flexibility in how they build queries, they must go through the legwork of building a set a queries to perform basic functions that legacy tools provided out of the box (e.g. exporting plans and simulation results). This results in added cost and an increase to the barrier of entry for missions considering Aerie. In fact, the first user of Aerie found it necessary to build a command line tool for Aerie ([aerie-cli](https://github.com/NASA-AMMOS/aerie-cli)), which they graciously provided back to the community and is now maintained by the Aerie project.
- Similarly, since Aerie lives in the greater ground system ecosystem where tools often communicate to each via files, common file formats are especially useful. Missions often don't want to go through the work of creating their own file formats if pre-built ones are sufficient.

In addition to the flexibility provided by GraphQL, there still seems to be a need for Aerie to offer an "out of the box" solution (file formats and standard queries) that works for most use cases and reduces the workload on missions.

## References

- https://tyk.io/
- https://www.apollographql.com/
Loading