Listening to the people I’ve spoken to this week then a picture may not be worth a thousand words. But those folks tend to prefer the command line over the GUI. If you’re in that camp you know where the source code to NetKernel is and you’ve probably read it. This post is for the rest.
Following on from Essence of ROC I’ve decided to do a series of concept maps of the ROC principles. Concept maps are pretty good at visually showing relationships between concepts. In fact they seem pretty close to RDF when represented as a set of proposition triples. Each concept is shown as a rounded box with the concepts name centred within it. Connecting between the concepts are linking phrases. These can be anything that makes sense within the domain. Unlike UML and more structured modelling languages there are no rules.
So first let’s look at a map that is based on the concepts we explored earlier in Essence of ROC. We ask the question “What is a resource?” and this forms the centre of our map with resource highlighted in orange.
We can see that this visual representation is pretty compact and although it potentially fails to capture some of the fine detail it gives a clearer high-level view. Of course we could add extra fine concepts to the map but that might hinder more than it helps. So my tendency will be to present a clear concept map and a minimal associated prose to fill in a few blanks if necessary. It might be nice to have little comment boxes like UML and nCoDE but unfortunately the tool I’ve been using doesn’t support them.
Compare this map to the mentioned principles with their associated proposition triples. (The observant of you will note that I’ve dropped the last principle about transreptors; thank you for those who pointed out it that it might be better left off, with hindsight I realise you were right because the concept of transreptors much better fits into the subsequent section.)
Everything is a resource
- Resource has an Identifier
Endpoints embody resources in software
- Endpoint embodies one or more Resource
Requests act upon resources
- Request act upon Resource
- Request handled by Endpoint
- Endpoint returns Response
- Request specifies Identifier
- Request specifies verb
Representations transfer state
- Request transfers Representation
- Response transfers Representation
Spaces host endpoints
- Space hosts Endpoint
- Space provides Address Space
- Address Space has for every resource an Identifier
Request Scope determines the resolution of a request
- Resolution resolves a Request
- Request specifies Request Scope
- Request Scope is a list of Space
- Resolution resolves to Endpoint
Endpoints can issue requests
- Endpoint can issue Request
Exploring the types of Endpoint Now we have the foundation as a concept map, I want to push forward and add in some more of the concepts. First up let us explore some of the variants of endpoint:
Endpoints come in four varieties, Overlays, Transports, Accessors and Transreptors (yes this is where it fits).
Overlays wrap a space, as such they manage access to the wrapped space from the host space. Overlays have many uses including implementing a simple import of one space into another.
Transports are endpoints which don’t embody any resources and no requests can resolve to them. What they do is receive events from outside the address space and convert them into requests and issue them into their hosting space.
Transreptors are again endpoints that don’t embody any resources. They convert representations from one form to another. Their purpose is to adapt representations from what an implementing endpoint provides to what a requesting endpoint wants. A simple example being a compiler that takes a sequence of characters and transrepts to an abstract syntax tree.
Accessors, in a sense, are the most obvious of the endpoints. They do directly provide an embodiment of one or more resources. For example a File accessor maps the files within a filesystem to resources within the host space with identifiers starting with “file:” The file accessor resolves SOURCE, SINK, EXISTS and DELETE requests which have a direct effect on the file on the filesystem. The file accessor is an example of a stateful accessor because if models a resource which has state. Stateless accessors typically model transformations or language runtimes. These embody derivative resources which depend upon the state of other resources rather than any state which they directly contain. For example consider the Groovy runtime accessor which has no state but which provides the response from executing a given groovy program. Usually these stateless or service accessors only implement the SOURCE verb.
Minor practicalities of Modularity This section has a couple of concepts (modules and prototypes) relating to the the modularity of systems built around the resource oriented concepts.
A module is the unit of deployment. It deploys one or more spaces with their endpoints. NetKernel supports dynamically deployable modules and also pluggable module implementations. Currently only one module implementation technology is supported, this is the Standard Module, though other non-supported implementations such as the legacy NetKernel3 Classic Module and a low-level Java Module are available.
Spaces can host prototypes in addition to endpoints. A prototype exists to allow the creation of new endpoints based on an implementation provided in a library space. It is often necessary to create new endpoint instances rather than simply issue a request to an existing endpoint when the endpoint depends upon it’s location, i.e. an overlay or transport.
So what makes it Tick? This section shows how the kernel at the heart of NetKernel lies a kernel which acts as the intermediary middleware between requests.
The kernel mediates between requests. Although we logically think of endpoints issuing requests to other endpoints the reality is that endpoints have no direct coupling between each other. What actually happens is that requests are issued to the kernel and it performs resolution of the request to determine an endpoint to process the request based upon the request scope which is contained with the request. When the request has been resolved it is then forwarded on to be evaluated by an endpoint. If an endpoint doesn’t return a response representation that the requesting endpoint desired then the kernel will also attempt resolution and evaluation of a transreptor to change the representation.
The kernel also enables the implementation of asynchronous requests by handing of a request into a queue that is then serviced by a worker thread pool. This enables the calling endpoint to perform many request concurrently.
One of the big wins with ROC is the ability to cache results of computation. The kernel maintains a representation cache which is checked before it considers forwarding a request to an endpoint. In addition the kernel maintains a resolution cache which is checked before it attempts to resolve a request.
Pulling it all together With nothing more to be said, here is the complete concept map covering everything we’ve discussed: