-
Notifications
You must be signed in to change notification settings - Fork 1
Hypermedia workflows redux
Take the hypermedia "work order" media type built for the 2013 hack day, and build clients that understand how to "make a move" and perhaps "present a board". "Work" here means making an actual chess move.
The goal is to produce a "workflow-like" system which can play a distributed game of chess.
-
The "Worker" would be given (using the "work needed" media type from 2013).
- a board with (chess) pieces on it
- a number of legal moves
- hypermedia controls to provide the legal move
-
The server would
- provide various URLs where chess playing workers may seek moves to be made.
- provide "current board" and "legal moves" to the workers
- accept the moves made by these workers.
Before the event, we need to define the worker media type (already done), along with the language of the board and legal moves (should happen on this page).
For the board, I suggest a FEN String, as it's plain text, easy to understand and helpful when debugging a board. There are also visualizations of FEN strings available that could be used by participants the hack day, tools to create test data, there are libraries for checking validity, checkmates, loading/saving FEN, getting a list of legal moves, making moves etc.
For the legal moves, I'm a fan of PGN (i.e. the subset of PGN which identifies a move. So e.g.
Nxf7
would identify a Knight taking on f7. The list of legal moves could be as simple as a whitespace-separated String of these, and the chosen move would be one of those "words".
Static files should be made to serve as test data for clients, using hypermedia controls to guide them through a fictional game of chess when served using a simple web server.
A "pick the first legal move" client should be built to serve as a tester for servers.
At the event, some people may already have working chess playing clients or servers, and will wire these together.
Others would build these at the venue, and advertise their server on a github page or on a whiteboard.
Adventurous souls might use <a hrefs>
from the github page to start off a random game :)
In addition to the above, where the server knows the rules of chess, a couple of more components could be commissioned at the hack day, in order to produce a server that doesn't know chess either, by adding a "supervisor" to the mix:
-
The ignorant server would (in addition to what the server does):
- when a worker makes "a move" provide a "feed" of decisions to be made to another type of worker, called the supervisor
- provide the "current board", "chosen move" to the supervisor
- provide hypermedia controls for the supervisor to make its decision on how to proceed.
-
The chess supervisor client would:
- ask the ignorant server for the next "ruling"
- inspect the board, update it, compile a list of new legal moves,
- use hypermedia controls provided by the server to provide its results.
Before the event, we need to define the supervisor media type(s) (see below).
Static files should be made to serve as test data for supervisor clients, using hypermedia controls to guide them through various chess games when served using a simple web server.
A "compile a list of a couple of random moves" supervisor should be built to serve as a tester for servers.
Some participants would make supervisor (clients), while others would make servers that could talk to both supervisor and chess playing clients.
If the full proposal is chosen the end result would be:
- chess playing clients of various types that all can select moves (at random, using AI, asking a human)
- supervisors that decide if a move is good, the current board, and the list of legal next moves
- a few servers that service the needs of chess playing clients only
- a few servers that service the needs of both chess playing clients and supervisors
In the end we should be able to play a good game of chess. Maybe someone will write a server or supervisor that (when a move has been chosen) uses (creates work for) the Text-to-Speech worker built two years ago to read the moves out loud as they are accepted by the supervisor, perhaps with witty commentary.
Very likely, the server component needs to keep the various games apart. Without this, the same client component would (could) be playing both black and white. This isn't necessarily a bad thing, but to make this more real-world, the server will probably have to have a concept of "creating a game", but also to have separate queues of "make a move" work, and ways of connecting games to such queues.
For example, a server might make a queue for "human players" and another queue for "bot players", and when a game is created, it knows to alternate the "work" between these two queues. The client connectors would then of course have to be set up to service the "human players" queue or "bot players" queue.
To keep things simple for the purpose of this hack day, I propose that servers use Collection+JSON for these queues.
A supervisor process makes requests to a feed of some sort of documents that contain "requests for supervision, and hypermedia controls in the response typically guide the client to send a document of type "decisions" back to the server if all goes well.
Instance documents of this type are typically sent from a server to a supervisory client. The sender has some workflow that is executing, and something has prompted it to ask the recipient to make a decision on what to do.
To make things easy let's use a HAL based document, for (somewhat) easier tooling and out-of-the-box understanding at a low level
Here's an example of a supervisor that is being told that we're at a pristine board, and the first move was "e4", with the URL to where the server wants the supervisor's decisions to be sent. The "data" sent comes from a worker that knows how to make a move.
GET /chess-game/23j89nuklyedsio/
Accept: application/vnd.mogsie.workflow.events+json
200 OK
Content-Type: application/vnd.mogsie.workflow.events+json
{
"current-state" : "tag:chess.mogsie.com,2001:game-in-progress",
"data" : {
"board" : "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1",
}
"recent-events" : [
{ "type" : "work-completed",
"name": "make-a-move",
"data": { "move" : "e4" }
},
],
"_links": {
"curies" : [{
"name": "workflow",
"href": "http://TBD/{rel}",
"templated": true
}],
"workflow:make-decisions" : { "href" : "./make-decisions" },
}
}
- current-state — a URI that identifies the current state of the workflow execution in question. In this case we're in a chess game.
- data — Some data that was previously tucked away by earlier interactions with supervisors, in this case the current chess board.
- recent-events — An array of objects that each describe something that has recently happened in this game
- type — string: always "work-completed", indicating that some work that was previously started was completed (“data” contains the result of the worker’s work).
- name — The name previously given to the work that completed, to disambiguate between different work completing.
- data — The actual output of the worker (if any), in our case the chosen move.
Links in the document are as follows:
- make-decisions — A writable hypermedia control that the recipient (supervisor) may invoke when it is ready to do some supervising. When doing so, a POST request is sent to this URI, with content of type application/vnd.mogsie.workflow.decisions+json, containing the decisions.
The structure of the document is as it is in order to be able to evolve into a larger media type with more options that cater for timeouts, aborting workers, external signals and so on.
Instances of this media type are typically sent when invoking the make-decisions hypermedia control. Instances of this media type describes
- The new resting state (identified by a URI).
- Any work that might need to happen (in our case we typically want someone to make a move).
Here is a simple example, the supervisor instructing a "chess playing worker" to make a move, telling the worker the current board layout and the list of legal moves (required inputs to that worker).
POST /chess-game/23j89nuklyedsio/make-decisions
Content-Type: application/vnd.mogsie.workflow.decisions+json
{
"current-state" : "tag:chess.mogsie.com,2001:game-in-progress",
"data" : {
"board" : "rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR b KQkq - 0 1"
},
"decisions": [
{ "type" : "schedule-work",
"name" : "make-a-move",
"queue" : "bots",
"work" :
{ "type" : "http://mogsie.com/static/workflow/make-chess-move",
"input" : {
"board" : "rnbqkbnr/pppp1ppp/8/4p3/8/8/PPPPPPPP/RNBQKBNR b KQkq - 0 1",
"legal-moves" : [ "a5", "a6", "b5", "b6", "c5", "c6" .... ]
}
}
}
]
}
This decision asks the server to find a worker that can make a (new) chess move. The local name given to the work is "make-a-move" which would be used later when that completes, to differentiate it from other types of work.
The fields of the application/vnd.mogsie.workflow.decisions+json
document:
- current-state — A URI, identifying the new resting state
- data — new data that should be "kept", for the next supervisor
- decisions — an array containing decisions
- type — A string, identifying the type of decision
- schedule-work: Indicates that the recipient should try to get some work done.
- name — A name given to this piece of work, so that it may be recognised when it's done
- queue — A name of a queue to place this work in
- work — Describes the work that needs to be done, a Work-order.
- type: The type of work (a URI)
- input: An object describing the input required by the type of work
- type — A string, identifying the type of decision
In this scenario, the previous discussion on queues still holds true, but for a truly generic server, the supervisor would (when scheduling work) would have to be able to control which "queue" work should be placed in, therefore knowing a lot about what type of workers would be servicing each queue.
In this scenario, the supervisor might have a bot play five or six moves, before handing over black or white over to a human. Or the other way around, two humans might be given work until e.g. a piece is lost by one side, after which a bot takes over.
The services could be composeable, a supervisor might ask two or three (different) bot queues to see what they think should be the next move, and only present two or three of these moves to a human player. A supervisor might ask two bots and a human, and overrule the human if the bots disagree. A supervisor could (as a teaching tool) refuse any move (i.e. re-issue the same piece of work) until the human selects the "correct" move.
Home :: Code of Conduct :: People :: Agenda :: Travel :: What Is RestFest?