
Tokamak Energy develops a quench resistant magnet .
More on APIs
Recently I got the inital implementation of application isolates working
(in browser only, without pulling application code from remote location)
and as part of that did a pass on API implementations.
This can be accomplished by adding more precision to the @Api decorator:
I sent quite a bit of time developing with Hibernate (in Java world). It is a great piece of technology but one thing I never liked about it is the fact that entities can be attached and detached from the ORM session. For INSERTs vs UPDATEs AIRport got around this by maintaing an __originalValues__ property on each object retrieved from the database and diffing it with the passed in values on the "save" operation. But DELETEs cannot be just as easily maintained.
Object state is what keeps track of if the object has been deleted or not and what the original values of the object were. It is possible that the application developer wants to maintain all CRUD logic internally to the application (at least on certain APIs). If that's the case AIRport can accomidate that but scrubbing all object State when an API is called.
A accomplish this a new @SaveEntryPoint() decorator will be introduced. A method decorated with this decorator will always take an array of the corresponding entity objects and nothing else and there may only be one @EntitySave() method per entity type. This is necessary for the framework to make a determination what method to invoke for a given entity- if there is more than one than it becomes unclear what method to invoke. Note that for any given save operation, this acts as an entry point. The entire object sub-graph that belongs to this Application's schema will be processed without calling any other @SaveEntryPoint()s for nested objects.
Locking down APIs
One thing that is likely be needed in the future is the ability to differentiate between "Application APIs" and "External APIs". An Application developer should be able to lock down APIs to be either other Application facing or External facing (like web UI, or anything else not running in an App isolate).This can be accomplished by adding more precision to the @Api decorator:
@Injectable()
export class AnApiClass {
@Api({ applications: true, external: true})
async anApi(): any {
...
}
}
Current thinking is to leave the API wide open by default and allow the
developers to lock it down as needed.
AIRport path
One of the tradeoffs that AIRport had to make is to give up some of the elegance when it comes to deleting records but instead not have to maintain a session.I sent quite a bit of time developing with Hibernate (in Java world). It is a great piece of technology but one thing I never liked about it is the fact that entities can be attached and detached from the ORM session. For INSERTs vs UPDATEs AIRport got around this by maintaing an __originalValues__ property on each object retrieved from the database and diffing it with the passed in values on the "save" operation. But DELETEs cannot be just as easily maintained.
Ackward DELETEs
The best I can come with for deletes so far is the following:
/*
* Marks the object as deleted in
*/
markAsDeleted(record)
/*
* True if record is deleted, false otherwise
*/
isDeleted(record)
This API allows the developers to explicitly mark a given
object as deleted and also detect if an object has been
marked as deleted. This delete API is rather crude but
purposely makes the "save" operation the segway for
all entity based insert, update and delete operations (
there is also no explicit update for entity API). Of
course the developers are always free to write explicit
update and delete statements, expecially for bulk operations.
Rare deletes
It is worth noting that I don't exect deletes to be a common operation. There really shouldn't be much reason to delete records, expecially since they can be split into time bound Repositories and archived when no longer actively needed. On top of that in AIRport no data is really ever deleted since it is preseved in the transaction logs. Hence I don't exect high usage for the delete operation, just lots of archiving.Locking down object state
Thinking about deletes made me realize that one more API lockdown can be added to @Api - ability to pass in Object State.Object state is what keeps track of if the object has been deleted or not and what the original values of the object were. It is possible that the application developer wants to maintain all CRUD logic internally to the application (at least on certain APIs). If that's the case AIRport can accomidate that but scrubbing all object State when an API is called.
@Injectable()
export class AnApiClass {
@Api({ objectState: true})
async anApi(): any {
...
}
}
Again the default will be to leave the API open to external
modifications, at this point it is hard to determine what will
likely be the most common scenario - direct modifications from
modern think UIs or more traditional lockdown approach of
server side development.
@SaveEntryPoint()
To build on top of initial application interability thoughts I'm proposing a new decorator to mark points where save operations can cascade. As a recap - save operations that cross application schema boundaries will call into the logic of the Applications that contain the schemas with nested objects. That way the application always has control over how the objects in it's schema get saved and can run the necessary validation logic to make sure that records are maintained in a proper order.A accomplish this a new @SaveEntryPoint() decorator will be introduced. A method decorated with this decorator will always take an array of the corresponding entity objects and nothing else and there may only be one @EntitySave() method per entity type. This is necessary for the framework to make a determination what method to invoke for a given entity- if there is more than one than it becomes unclear what method to invoke. Note that for any given save operation, this acts as an entry point. The entire object sub-graph that belongs to this Application's schema will be processed without calling any other @SaveEntryPoint()s for nested objects.