ARGON
Documentation
Login

The day to day work of a developer is, of course, editing and testing code. In the world of ARGON, code is published as document entities.

Entry points

As discussed in the Entities page, entities contain references to code that provides the behaviour for that entitiy. That code is contained in software modules exposing a suitable interface.

There's a few kinds of code references an entity might make:

Either way, ARGON code is event-driven: procedures written to handle specific events. One never writes daemon code that sits there blocked waiting for something to happen; one never writes startup and shutdown event handlers that prepare "running state", as all state that persists between handlers is managed by the system. Different handlers for the same entity might be running at once on different nodes, and the system will handle distributed persistence, load balancing, and the like.

Personas

An entity ID always points to a specific entity in an ARGON cluster somewhere, but it also contains an optional "persona field" that allows a given entity to have an unlimited number of different entity IDs referring to it - exposing arbitrarily different behaviour.

MERCURY requests are routed to the same actual entity regardless of the persona field, but the contents of the persona field is made available to the entity when it handles the request. The persona field, if present, is protected by a cryptographic signature, granting the entity the ability to create entity IDs referring to itself with an arbitrary persona field (and denying that ability to third parties, although a third party can strip the persona field off an entity ID to get the ID of the physical entity).

Personas let an infinite number of "virtual" entities exist, while only one "real" entity needs to actually be created in the cluster. The entity just presents a different persona when accessed through a different ID. This makes it easy for entities to provide gateways to third-party systems by representing third-party objects as entities, embedding the identity of the third-party object in the persona field, for instance. Or an entity could do something like provide a distinct entity representation for every integer, by embedding an integer in the persona field, and present an interface that publishes various facts about that integer: its representation in Roman numerals, its prime factors, and so on - by computing them on the fly.

Entity context

A lot of the entry points mentioned above run in "the entity's security context". This gives the code access to:

However, code may choose to run other code in a "sandboxed" dynamic context which relinquishes some of those rights, or introduces limits on space and time consumed by the computation.

Entity state

The state within an entity, managed by TUNGSTEN, is a number of named CARBON knowledge bases, known as "slices". The names can be any object, but are usually symbols or lists of symbols.

Names starting with a $ symbol are "well known" names, reserved by the ARGON system to have special meanings. They are:

The slices which are listed in $CARBON are "directly published"; when a "DOWNLOAD" CARBON request comes in, the contents of all slices which the access control lists deems visible are returned. However, as well as actual knowledge, those knowledge bases may also contain "gateways".

The DOWNLOAD request, as well as sending the contents of $CARBON, will also automatically append tuples declaring exposed interfaces declared in $MERCURY - and the hardcoded volume administration interface number -2, if the entity is a volume entity, unless it's already declared in $MERCURY. There's no need to hardcode in interface 0 (CARBON) or -1 (entity administration) as they are present on all entities, but if they are declared in $MERCURY in order to attach extra metadata, that will be included. These interface declarations contain the mapping from the interface symbol to the entity-specific interface number used to compactly represent the interface on the wire, and any public metadata provided in $MERCURY, including transit security requirements - so that clients can be advised of requirements, rather than having to send a request and have it rejected. Note that this metadata may also, optionally, be bundled in the EID returned by the "Access the entity's own ID" operation, for the same reason.

A gateway is a CARBON knowledge pattern with some variables in. When the gateway is encoded to send back in the original request, they are rewritten so the recipient just receives the knowledge pattern that forms the "head" of the gateway and an opaque signed token that forms the "tail"; they can request, via the CARBON protocol, to have the receiving node match a CARBON knowledge pattern matching the gateway's pattern and get back a list of matching results. The signed token contains a reference to the access control list entries that granted the caller access to find the gateway in the first place, and when a request comes in, the request is checked against those entries to ensure that the caller still has access to the gateway.

How the node then handles that request depends on the kind of gateway, as declared in the directly published slice.

One kind is a static gateway, which names a slice within the entity's state containing further knowledge exposed via CARBON, except remote entities don't get to download the whole lot; the incoming pattern is matched against knowledge in that slice, and the response returned. This enables an entity to contain a very large knowledge base and provide access to it, without letting/encouraging the world just download the whole lot. The same slice might be made available as a directly published slice via a suitable persona if bulk download is desirable as an option.

The other kind is a dynamic gateway, which names a code module that is invoked in the entity's security context and given the pattern, and returns a list of responses. This allows arbitrary code to answer CARBON queries.

But, what about personas? How can an entity ID with a persona field make an entity produce different behaviour? Well, when a CARBON or MERCURY (CAESIUM doesn't care about personas) request with a persona field comes in, different slices are consulted to find the behaviour. Although a persona field is defined in the entity ID format to be arbitrary data, in practice the proposed implementation will always store two pieces of information in there, protected by a cryptographic signature. The first piece of information is a symbol, the "persona scheme", and it is used as a prefix to the well-known slice names; MERCURY requests will be handled by the list stored in the slice whose name is a list with the persona scheme as the first element and $MERCURY as the second, and likewise with CARBON requests.

The second part of the persona, the "parameter", is arbitrary data and is provided as an optional argument (unset for non-persona requests) to any code invoked to handle CARBON dynamic gateways or MERCURY interface handlers.

Oh, and that cryptographic signature on the persona field, which must be valid for the request to be accepted? Well, there's a slice whose name is a list with the persona scheme as the first element and $CONFIGURATION as the second element which is consulted to find the secret used to check that signature - or to create the signature when minting an entity ID with a persona. If the slice or the keypair within doesn't exist when the ID is minted, one is created.

Debugging

So much of a programmer's time will be spent interacting with document entities containing source code, and interacting with prototype entities referencing that source code through an administrative interface that lets one edit their state directly. However, the administrative interface also lets one put an entity into debug mode.

When an entity is in debug mode, all handlers that are invoked on it appear in your debugging interface with an interface that lets you single-step through them, examining their state as you go, or letting it run until it hits a breakpoint, logging chosen kinds of activity (reads or writes of the persistent state, requests to other entities, etc) as it runs.

The language

ARGON supports using multiple different programming languages for handlers, but the default one is called CHROME. It's a purely functional language, but with uniqueness typing to manage mutation-esque operations in the manner of Concurrent Clean.

Largely, handlers are functions mapping the current state of the system and the details of the event being handled to a new state for the system. Operations on the state of the system would include reading and writing entity state, communicating with other entities (which includes, through gateways, communication with the Outside World of HTTP and such familiar protocols), and sending back a response to the event if one is needed.

Embedded development

There is one exception to the rule that all code lives within entity handlers. It's possible to write code that runs directly "in the kernel", which is useful for extending ARGON itself, or writing device drivers, or real-time tasks that have to respond to events within a bounded time interval too small and strict to allow disk access and competing with other handlers to get involved, or when writing code for minimal ARGON nodes that don't have the infrastructure required to host proper entities.

However, in such cases, your code is still edited inside an entity. But in this case you'll be telling the "node entity" representing the computer that's intended to run it to load it from the published module you're writing it in, and the debugger's a lot more primitive...