Aphorio v0.6.3

Services

In Aphorio the service architecture is built for simplicity so that it can scale to accomodate custom third-party extensions without refactoring the rest of the application. Generally, the service architecture comprises three locations and a universal format:

Universal Service Format

All services in Aphorio comprise the same high level format, which is an object of two properties: data and service.

The data property stores the data to transfer, either between libraries locally or across the network between machines. This data is defined in the service definition file, which is further explained in the next section.

The service data property is just a string type. This string is the name of both the service consuming this data as well as the TypeScript interface name that defines the data. See this simplified example:

{ data: { frequency: 20, records: 1000 }, service: "services_statistics_change" }

Service Definitiions

The service definition file, /lib/typescript/service_registry.d.ts, is just a TypeScript definition file containing two things. Most of the file comprises TypeScript interface definitions to define all the supported service data types. The bottom of the file contains a union of maps, which defines the relationship between the provided service definitions above to their TypeScript interface names.

The goal of this approach is to provide a singular identity to both a service consumer and definition. There is a single location to reference all service definitions against a single name which always accompanies the data. This also simplifies maintenance and troubleshooting. The above sample is defined like this:

interface services_statistics_change { frequency: number; records: number; } // Saves data about how much data to gather and send to the UI for statistics graphs

Routing the Data

A given service library will know what data format it expects to receive due to type definitions of its function arguments, but that data must get to the appriorate function first. The /lib/transmit/router.ts file provides a map that associates service name to the receiving function for all data coming off the network interface. The above exmaples are routed like the highlighted line in following code:

import dns from "../services/dns.ts"; import docker from "../services/docker.ts"; import fileSystem from "../services/fileSystem.ts"; import hash from "../services/hash.ts"; import log from "../core/log.ts"; import message_inspection from "../services/message_inspection.ts"; import notes from "../services/notes.ts"; import os from "../services/os.ts"; import ports_application from "../services/ports_application.ts"; import servers from "../server/index.ts"; import socket_list from "../services/socket_list.ts"; import statistics_resources from "../services/statistics_resources.ts"; import terminal from "../services/terminal.ts"; import test_http from "../services/test_http.ts"; import test_performance from "../services/test_performance.ts"; import test_runner from "../test/runner.ts"; import udp_socket from "../services/udp_socket.ts"; import websocket_test from "../services/websocket.ts"; const router = function transmit_router(socketData:socket_data, transmit:transmit_socket):void { const services:string = socketData.service, actions:transmit_receiver = { "services_compose_container": docker.receive, "services_compose_variables": docker.receive, "services_dns_input": dns, "services_file_system": fileSystem, "services_hash": hash, "services_log": log.receive, "services_message_inspection": message_inspection.set, "services_notes": notes, "services_os_all": os, "services_os_devs": os, "services_os_disk": os, "services_os_intr": os, "services_os_main": os, "services_os_proc": os, "services_os_serv": os, "services_os_sock": os, "services_os_stcp": os, "services_os_sudp": os, "services_os_user": os, "services_ports_application": ports_application, "services_server_action": servers, "services_socket_application": socket_list, "services_statistics_change": statistics_resources.change, "services_terminal_resize": terminal.resize, "services_test_browser": test_runner.receive, "services_test_http": test_http, "services_test_performance_input": test_performance, "services_udp_socket": udp_socket, "services_websocket_handshake": websocket_test.handshake, "services_websocket_message": websocket_test.message }; if (services === "services_terminal_resize") { const data:services_terminal_resize = socketData.data as services_terminal_resize; if (data.section === "compose-containers") { docker.resize(socketData, transmit); } else { terminal.resize(socketData, transmit); } } else if (actions[services] !== undefined) { actions[services](socketData, transmit); } };

Directory of Services

The project provides a single directory, /lib/services, to store service specific libraries. This single location exists for convenience of maintenance, but a given service library can exist anywhere a third party author wishes so long as it is included in the router file mentioned above.

Further Reading

For more detailed explanations of each supported service please see the App Services feature section in the running Aphorio dashboard UI. This content provides each service definition along with all referenced types from the given definition and a brief explanation for each service.