+ All Categories
Home > Documents > The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Date post: 28-Dec-2015
Category:
Upload: marilynn-lynch
View: 224 times
Download: 0 times
Share this document with a friend
Popular Tags:
79
The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail
Transcript
Page 1: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

The Inverse World

of the FOREST

Object Web

Duncan Cragg

Part 2 - Technical Detail

Page 2: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Let's take a closer look at a FOREST Object...

Page 3: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

FOREST Objects Have Unique Ids - for those Links

UID

Page 4: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

FOREST's Data Model is based on JSON

{ : "..": :}

UID

Page 5: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Let's go back to the string joiner example to see what it

looks like close up

{ : "..": :}

UID

Page 6: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Greetings

World

Greetings World

uid-2-2

uid-3-3

uid-1-1

Page 7: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], :

Here's what our joiner Object may look like in JSON:

This is how something like classes can be indicated, although there's no concept of

class in FOREST

This is how something like classes can be indicated, although there's no concept of

class in FOREST

Page 8: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Greetings World", :

Here's what our joiner Object may look like in JSON:

The result; obvious enough

The result; obvious enough

Page 9: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Greetings World", "items": [ : ]}

Here's what our joiner Object may look like in JSON:

We'll put the items to be joined in a list

We'll put the items to be joined in a list

Page 10: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Greetings World", "items": [ "uid-2-2", "uid-3-3" ]}

Here's what our joiner Object may look like in JSON:

UIDs pointing to the FOREST Objects to join

UIDs pointing to the FOREST Objects to join

Page 11: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joinable" ], "text": "Greetings"}

Here's what the first joinable Object may look like:

Page 12: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Joiner isn't likely to be a highly re-used Object Type!

{ "is": [ "joiner" ], "result": "Greetings World", "items": [ "uid-2-2", "uid-3-3" ]}

Page 13: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

But there are many Types that can be standardised

{ "is": [ "atom" ], "title": "Universe Blog", "feed": [ { "title": "My Space Trip", "updated": "2008-02-16T23:44:00Z", "weblink": "http://uniblog.org/..", "text": "Yesterday, I was.." }, .. ]}

Page 14: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

All such JSON Data Types will fall under a new sub-type of

JSONContent-Type: application/forest+json

.. which will explicitly be a hypermedia - or hyperdata - type

Page 15: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

In FOREST, we follow Postel, being strict in only generating

standard types and schemas ..

Content-Type: application/forest+json

{ "is": [ "atom" ], ..

Page 16: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

.. but only looking for what we really need when consuming them

{ "title": "Universe Blog" }

Page 17: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Back to Joiner:those Ids map to URLs

URL

Page 18: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Greetings World", "items": [ "uid-2-2", "http://the.net/uid-3-3" ]}

If an Object is remote and you need to locate it, use its URL!

Page 19: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

If you fetched that URL, you'd get a JSON representation

{ : "..": :}

URL

Page 20: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

GET /uid-3-3 HTTP/1.1Host: the.net

Page 21: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

GET /uid-3-3 HTTP/1.1Host: the.net

HTTP/1.1 200 OKEtag: "1"Cache-Control: max-age=10Content-Type: application/json

Page 22: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

GET /uid-3-3 HTTP/1.1Host: the.net

HTTP/1.1 200 OKEtag: "1"Cache-Control: max-age=10Content-Type: application/json

{ "is": [ "joinable" ], "text": "World"}

Page 23: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

There are three ways that we can find out if the remote object

has changed

For now, we'll just look at good ole' poll...

Page 24: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

GET /uid-3-3 HTTP/1.1Host: the.netIf-None-Match: "1"

HTTP/1.1 304 Not ModifiedEtag: "1"

Page 25: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

GET /uid-3-3 HTTP/1.1Host: the.netIf-None-Match: "1"

HTTP/1.1 200 OKEtag: "2"Cache-Control: max-age=10Content-Type: application/json

{ "is": [ "joinable" ], "text": "Universe"}

New EtagNew Etag

Changed contentChanged content

Page 26: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Greetings World

Greetings

World

Page 27: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Greetings World

Greetings

Universe

Page 28: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Greetings Universe

Greetings

Universe

Page 29: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

So remote Objects can look much the same as local ones

Page 30: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

The FOREST framework will handle the polling, timeouts and

retries to achieve this illusion

Page 31: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

You may need different domain-level retry logic for remote Objects

- especially ones you don't own

Page 32: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Programming FOREST Objects

Page 33: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

"An object's state evolves

as a function of its own state and the state of other objects, local and remote, that it observes directly or indirectly through links"

Page 34: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Remember what the internal animation looks like?

Page 35: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

This is where the traditional methods and Objects hang out

Page 36: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Most implementations will use a similar API to the one about

to be described in pseudo-code

Page 37: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Any Declarative language would be built on top of this API

But even using it directly gives a strong Declarative style

Page 38: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Before this, the Object is locked and prepared

Before this, the Object is locked and prepared

May also be fired when the framework thinks

things need refreshing, like on a creation or re-cache

May also be fired when the framework thinks

things need refreshing, like on a creation or re-cache

evaluate(){ :}

This is the only callback your Object gets. It's fired

when a dependent changes - or arrives first time - so the Object can evaluate its new current

state

This is the only callback your Object gets. It's fired

when a dependent changes - or arrives first time - so the Object can evaluate its new current

state

Page 39: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") :} Access to the Object's JSON

is via content() with a JSON path argument

Access to the Object's JSON is via content() with a JSON

path argumentThis is writing to a

temporary copy of the content so no changes are

public yet

This is writing to a temporary copy of the

content so no changes are public yet

Second argument allows setting the value.

Second argument allows setting the value.

Page 40: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") foreach link in content("items"){ : }}

Loop through the links to joinable Objects

Loop through the links to joinable Objects

Page 41: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") foreach link in content("items"){ text = contentOf(link, "text") : }}

Any Objects you don't read from

cease to be observed

Any Objects you don't read from

cease to be observed

Marks or re-asserts as observing changes

on that Object

Marks or re-asserts as observing changes

on that Object

Returns value at given JSON path if

available

Returns value at given JSON path if

available.. or triggers a remote fetch

.. or triggers a remote fetch

Dereferences the link in the local cache..

Dereferences the link in the local cache..

Page 42: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") foreach link in content("items"){ text = contentOf(link, "text") if(!text) continue : }}

Item may not be fetched yet, or may

be 404ing

Item may not be fetched yet, or may

be 404ing

Could return and wait, or soldier on.. Here we ignore it

and carry on

Could return and wait, or soldier on.. Here we ignore it

and carry on

Page 43: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") foreach link in content("items"){ text = contentOf(link, "text") if(!text) continue contentAdd("result", text+" ") }} Doing the actual

joining workDoing the actual

joining work

Page 44: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ content("result", "") foreach link in content("items"){ text = contentOf(link, "text") if(!text) continue contentAdd("result", text+" ") }}

May persist new state May persist new state

Notifies all dependentsNotifies all dependents

Handles changes to notifying and observing

Handles changes to notifying and observing

Swaps to new public content and increments Etag

Swaps to new public content and increments Etag

Page 45: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

The JSON path "items:text" jumps across lists and links and returns a

list of the text values. These are then join()ed with " "s.

The JSON path "items:text" jumps across lists and links and returns a

list of the text values. These are then join()ed with " "s.

evaluate(){ content("result", join(content("items:text")," ") }}

Alternative implementation: much more declarative!

Alternative implementation: much more declarative!

Page 46: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

What if an Object wanted to get another's attention?

Page 47: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

For example, to get itself added to that target Object

Page 48: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Or to submit itself as a query Object to that target

Page 49: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Or to initiate some processing interaction with it

Page 50: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

(remember Objects don't get to see their observers)

Page 51: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Hello

Hello

Page 52: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Hello

Hello

World

Page 53: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

joinerjoiner

Hello World

Hello

World

Page 54: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Hello", "items": [ "uid-2-2" ]}

Here's the initial JSON of uid-1-1 without uid-3-3

Page 55: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joinable" ], "text": "World", "joiner": "http://that.net/uid-1-1"}

Here's what uid-3-3 looks like - notice its link to the joiner:

Page 56: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ notifying(content("joiner"))}

Now uid-3-3 can set up the notification of its state to uid-1-1

notifying() sets up notification from now on of uid-3-3's state to uid-1-1 - as

long as uid-1-1 starts observing back

notifying() sets up notification from now on of uid-3-3's state to uid-1-1 - as

long as uid-1-1 starts observing back

Page 57: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Here, such Objects are simply added

(without any check!) to the items list

Here, such Objects are simply added

(without any check!) to the items list

evaluate(){ foreach link in alerted(){ contentListAdd("items", link) } :}

The 'alerted' list is incoming notifications that don't have a current observation set

up by this Object

The 'alerted' list is incoming notifications that don't have a current observation set

up by this Object

Then uid-1-1 is alerted

Page 58: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

{ "is": [ "joiner" ], "result": "Hello World", "items": [ "uid-2-2", "http://the.net/uid-3-3" ]}

New uid-1-1

Page 59: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Notification or alert to uid-1-1 of uid-3-3's state uses POST

That's the second way to detect remote updates, after polling

Needs the notifier to initiate it, via alerting(), else no POSTs!

Page 60: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

POST /uid-1-1 HTTP/1.1Host: that.net

This update is pushed directly at the joiner - here is the joiner's id and host

This update is pushed directly at the joiner - here is the joiner's id and host

Page 61: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

This is FOREST-specific POST header usage

This is FOREST-specific POST header usage

POST /uid-1-1 HTTP/1.1Host: that.netContent-Location: http://the.net/uid-3-3Etag: "1"Cache-Control: max-age=10

Cache update information similar to GET response headers

Cache update information similar to GET response headers

Page 62: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

POST /uid-1-1 HTTP/1.1Host: that.netContent-Location: http://the.net/uid-3-3Etag: "1"Cache-Control: max-age=10Content-Type: application/json

{ "is": [ "joinable" ], "text": "World", "joiner": "http://that.net/uid-1-1"}

Page 63: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

In FOREST, HTTP is used for two-way, domain-independent

state transfer

You only need GET to poll or pull and POST to push

Clients are servers and vice-versa

Page 64: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

POST body is very much like a GET response

POST carries cache information and keeps caches fresh

POST is idempotent in FOREST

Page 65: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

POST is simply for timely and efficient state transfer in FOREST

POST is not used for events, messages, actions or commands

POST response is an open channel for returning any updates

Page 66: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

HTTP/1.1 200 OKContent-Location: http://that.net/uid-1-1Etag: "2"Cache-Control: max-age=10Content-Type: application/json

{ "is": [ "joiner" ], "result": "Hello World", "items": [ "uid-2-2", "http://the.net/uid-3-3" ]}

POST response can carry the current state of the target Object back to the POSTed

Object, if the target is marked as notifying it

POST response can carry the current state of the target Object back to the POSTed

Object, if the target is marked as notifying it

Page 67: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

A "more interesting Object" may be a new sub-Object that notified itself

to the POSTed Object

A "more interesting Object" may be a new sub-Object that notified itself

to the POSTed Object

HTTP/1.1 200 OKContent-Location: http://that.net/uid-9-9Etag: "1"Cache-Control: max-age=10Content-Type: application/json

{ ..}

In some interactions, you could use the POST

response to redirect to a more interesting Object

In some interactions, you could use the POST

response to redirect to a more interesting Object

Page 68: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

HTTP/1.1 303 See OtherLocation: http://that.net/uid-9-9Etag: "1"Cache-Control: max-age=10Content-Type: application/json

{ ..}

Could use 303 redirect instead

Could use 303 redirect instead

Page 69: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

HTTP/1.1 204 No Content

HTTP/1.1 403 Forbidden

Could have no new state to report

Could have no new state to report

Or may not be interested in the notification - may not want to observe that

Object

Or may not be interested in the notification - may not want to observe that

Object

Page 70: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Driving FOREST Interface Objects

Page 71: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Objects whose public state is driven from external interaction

are interface Objects

Page 72: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

The User Object is the most important interface Object

Page 73: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

But let's start with a simpler example: an Object that shows the temperature at some place

Page 74: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

newTemp(t){ new Evaluator(){ evaluate(){ content("temperature", t) } }}

On temperature callback thread: Evaluatorlocks the Object, sets it up, calls this evaluate() function, then handles any updates - just like

in normal evaluate() function

On temperature callback thread: Evaluatorlocks the Object, sets it up, calls this evaluate() function, then handles any updates - just like

in normal evaluate() function

You're on a callback that the temperature has changed:

Page 75: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Objects can create more Objects

Page 76: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ : contentListAdd("items", spawn(new Joinable("Universe", url))) :} Go into the "text" and

"joiner" fields, resp.Go into the "text" and "joiner" fields, resp.

Either something like this:

Page 77: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

evaluate(){ : contentListAdd("items", spawn(create( '{ "is": [ "joinable" ], "text": "Universe", "joiner": '+url+' }', joinableEvalFn))) :} The evaluate() function for

this sub-ObjectThe evaluate() function for this sub-Object

Or something like this:

Page 78: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Things not covered

• Lazy/eager modes: lazy means no observations but blocking while re-evaluating, with or without waiting for deps to evaluate or be fetched; first create always blocks; Object decached stops observation and blocks for first re-cache; not re-eval before cache expiry; saving deps' Etags to compare

• Glitches and eventual consistency• Cache-Notify URL on POST responses and GET requests

allowing updates to be POSTed directly into the cache as an optimisation - see Chapter

• Asymmetric APIs - see Chapter• Data editing - see Chapter• User Objects - see Chapter

Page 79: The Inverse World of the FOREST Object Web Duncan Cragg Part 2 - Technical Detail.

Help build the FOREST Object Web!

Website:http://forest-object-web.org

Google Group:http://groups.google.com/group/forest-object-web

Code:http://github.com/DuncanCragg/NetMash


Recommended