A view of Cordova, Spain

Highway

  • By Artem V. Shamsutdinov
  • July 28th, 2020

Quite a bit of code written as part of the Airport effort really has little to do with the concept of Autonomous Interdependent Repositories (AIR).
Here is a list core, already working features that are needed for Airport to function but are not strictly part of it:

  • Entity Decorators
  • Query Language
  • DDL generation
  • Query object generation
  • Dependency Injection Framework

In fact these can be used completely independently of Airport. So, I will soon be open-sourcing these features as their own project - Highway.

Highway design goals

The idea of the Highway project has been floating around my head for a while. Originally it was envisioned to be the traditional ("serverful") addon to Airport. It spawned from the realization that very few businesses using Airport would not have any centralized infrastructure. Most of them would probably have part of the data shared "globally", meaning the data is accessible to everyone. Hence a way to unite the purely group/personal oriented Airport data and globally accessible data behind a single front-end SDK.

Very recently I came to a realization that Highway isn't just an addon to Airport. In fact is more of the opposite. Highway can stand alone as a project of its own (providing a way to work with traditional client/server data) where as Airport is an addon to that.

With that in mind, here are the design goals behind highway:

Provide a better/more productive UI development experience

Current Javascript/Typescript ORMs fall short of what I would consider the "holy/grail" of ORMs. There is of course GraphQL but it does not tie itself to a relational database as a backing engine and requires writing and maintaining server-side code. Highway aims to provide a development experience that is inspired by GraphQL but is deeply rooted in the relational data model.

Provide a seamless integration with scalable technologies

A website backed by a relational database has severe performance limitations. Any significant usage spikes can lead to degraded site performance or even an outage. This can be traced to the need for querying a multitude of objects to come up with queryable views. Relational data model just doesn't scale as well as document oriented alternatives (or if it does it's costs are much higher then they would be with a more performance oriented option). Highway aims to unify the NoSQL and relational worlds with a simple decorator. Given 2 entities:


@Entity()
export class Parent {

    @Id()
    @GeneratedValue()
    key: number;

    value: string;

    @OneToMany({cascade: CascadeType.DELETE, mappedBy: 'parent'})
    children: Child<[];
}

@Entity()
export class Child {

    @Id()
    @GeneratedValue()
    key: number;

    value: string;

    @ManyToOne()
    parent: Parent;
}
                    

The query originally defined here can be simply amended with an @View() decorator:


export class ParentDao extends BaseParentDao {
    @View()
    @Query<IQParent>(select({
            id: Y,
            value: Y,
            children: {
                id: Y,
                value: Y
            }
        }).from(p => ({
            p,
            c: p.children.innerJoin()
        }).where((parentId, notLikeChildValue, q) =>
            q.p.id == parentId
            && !q.c.value.like(notLikeChildValue)
        }).orderBy(q => [
            q.p.id.desc(),
            q.c.id.desc()
        ]))
    static selectWithChildren: (
           parentId: number,
           notLikeChildValue: string
       ) => Promise<Parent[]>;
}
                    

This decorator informs Highway that this query is actually served by a NoSQL view. Highway can then take care of all the required details of maintaining a relational database and a NoSQL front-facing store in sync.

Provide a seamless integration with FTS technologies

Quite a bit of the traffic going to modern sites deals with Full Text Search queries. While relational databases can and do support full text search they by their nature won't be as efficient as specialized solutions. Highway aims to hide the complexity of dealing with full text search implementations from the developer behind a simple @Searchdecorator:
@Entity()
export class Parent {

    @Id()
    @GeneratedValue()
    key: number;

    @Search()
    value: string;

    @OneToMany({cascade: CascadeType.DELETE, mappedBy: 'parent'})
    children: Child<[];
}
                        

Entities can then be searched for using a set of query related concepts:


export class ParentDao extends BaseParentDao {
    @Search()
    static searchIdsOnly: (
           searchString: string
       ) => Promise<number[]>;

    @Search()
    static searchWholeEntities: (
           searchString: string
       ) => Promise<Parent[]>;

    @Search()
    @Query<IQParent>(select({
            id: Y,
            value: Y,
            children: {
                id: Y,
                value: Y
            }
        }))
    static searchWithChildren: (
           searchString: string
       ) => Promise<Parent[]>;
}
                    

Highway aims to hide the complexity of integrating a full text search engine (if any) with a relational database or a NoSQL view provider

Provide a seamless integration with auto-scalable technologies

Very few sites start out large-scale. Quite often you have no idea how big the concept behind the site will be and how much performance optimization will be required to keep it running. Highway aims to integrate cloud-native tech like autoscaling NoSQL and Full Text Search (as well as other tech required to scale your solution) with you only specifying a simple flag of how you want the solution to be deployed. Once your site hits those high traffic marks Highway aims to make your transition to more cost effective solutions as easy as switching a value of that same simple flag.

Support as many implementations as possible

By default Highway will support the AWS stack to back its scalability options. The intent is to support as many solutions as is practical.