The ideal distributed system has many different machines with different architectures, focuses, specialities and so on. Some might be tiny microcontrollers, some might be home desktop machines and some might be giant server farms. The central innovation of this fantasy is that all the communicands talk the same language in the same way. Participating machines can securely and privately search each other's objects, look up information and trigger actions. All of these actions can be done efficiently through the use of scheme files that allow a machine to learn a lot about remote objects. A search of a main server for companies, for example, might yield an object that represents the company "MakingThings". This object would be hosted on the MakingThings server and will provide an API for interacting with the company. Logging in from work, for example, might let you first navigate to your house, but then see all the devices in your home. Programs could be written against this background of identical interfaces which would seamless weave objects from different systems together. That's the big picture. So how does this look from a Persevere point of view? Querying for Remote ObjectsQueying for objects is close to the local version,tfs = load( "http://remote_server.com/Users/?firstName="Tooth"&lastName="Fairy" ); What comes back are objects with properties that help remote systems use them correctly. { id:"http://<some_server>/class/id", property1: value, property2: value, property3: { "$ref", reference } } Perhaps the most important property is the id. It tells us which remote system holds the instance and of what class it is. Using Remote ObjectsOnce obtained, remote objects should feel as close to local objects as possible.ro.property = value ro[ "property" ] = value would cause a value to be assigned to the remote object's property. If the value is an object, its remote reference is assigned. variable = ro.property would read a single property into the local variable. Note, depending on the schema, this might come from a cache or it might result in a remote request. variable = ro.method( param, param ) try { ro.reference( ) } catch ( e ) { } GET http://localhost:8080/Customer/1 ({"id":"1", "firstName":"John", "lastName":"Doe", "age":41, "friend":{"$ref":"2"} }) A load( ) might perform quite differently, returning a reference, rather than a complete, serialized object The local system can attempt to read and write properties on the
object, call methods, etc. blind - as the local code see's fit. If the object signals it, the local machine can go to the remote system and request the class schema for the
instance. This schema can be fairly comprehensive, outlining
properties and methods, validations, parameters, etc. all of which can
very helpful toward increasing efficiency. The schema can also define which methods run locally and which remotely. This permits a great deal of flexibility for the object designer. Any regular properties that came back with the intial find can be used immediately by the calling program, of course, but these are only valid until the __cache_until date. Other properties, and those that hold references to other objects, not necessarily on the same machine, can be resolved when needed and results cached if possible. Despite all the long round trips, all these functions should be synchronous to give the easiest possible programming experience. SchemaFrom Kris:It's all through explicit configuration right now. Here is the example I
tested: Server A (in a jslib module): Class({id:"Customer", prototype: { add10:function(param){ console.log("called add10 with " + param); return param + 10; }, ... Server B (in a config file):
on Server B:
Server A says:
SecurityNo object should be released to any user that does not have permission to use it. This means that for remote references, user credentials need to be sent, authenticated then applied to authorizations.TransactionsTransactions are as important for remote objects as for local ones. When something fails in a transaction all changes, local and remote need to disappear. This should look like the pjs mechanism, perhaps.ImplementationWhat small things can be done to achieve as much of this vision as possible?
Are there efficiencies that are worthwhile like getting all properties when asked for one, or getting several objects at once, etc.? WHAT FOLLOWS IS NOT IMPLEMENTED YET: AND IS THEREFORE PURE FANTASY CreationLocally, of course, we say:lo = new LocalClass( ) How would we make a remote class, locally?ro = new RemoteObject( server, class name, parameters ) orro = remoteServer.new( classname, parameters ) This would give us a new object of the specified class, constructed with the supplied parameters and hosted on the specified server. Locally objects need to get saved periodically. We will always be sending data back to the server so this is not important. The last option of course requires that we already have a remoteServer object knows enough to pull this off. Perhaps if we have a schema for the object from the remote machine we can use that class definition (com.makingthings.ClassName) with the new operator? ro = new com.makingthings.ClassName( parameters ) This makes the class name less fluid, parameterizable, etc. remove( object ) orremoveServer.remove( object ) Future IdeasThere will need to be an altid mechanism that provides a second source for the object in the case the first fails. This is particularly important as larger systems are developed where key data must be found to even get started. |
