Update documentation to match the new `App` and `Model` classes
haydnv opened this issue · comments
These pages:
- https://docs.tinychain.net/guides/chain-persistent-mutable-state
- https://docs.tinychain.net/guides/object-orientation
- https://docs.tinychain.net/guides/host-your-service
Have been badly out-of-date since Cluster
was replaced by App
. We should update them based on the App
and Model
examples in the tests/apps
directory.
Hey @haydnv , I may need access to your gitbooks.for the time being if you could review the docs i'll add them to the comments.
Chain: persistent mutable state.
In order to serve a dynamic application, you’ll have to have a way of updating your service’s persistent state. To do this you can use a Chain, a data structure which keeps track of mutations to a Collection in order to maintain the consistency of that State across every replica of an
app.
class Persistent(tc.app.App):
__uri__ = tc.URI("http://127.0.0.1:8702/test/chain")
def _configure(self):
self.rev = tc.Chain.Sync(0)
tc.app.App.__init__(self)
# this method looks up the value of "rev" within a transaction
@tc.get
def version(self) -> tc.Number:
return self.rev
# this method updates the value of "rev" within a transaction
@tc.post
def bump(self, txn):
# note: the value of "version()" must be assigned a name
# in order to be addressable by the instance method __add__ below
txn.rev = self.version()
return self.rev.set(txn.rev + 1)
When you start a TinyChain host with an App definition, it will assume that there is a hosted app with the given URI (”http://…/app/test/chain” in the example above) and attempt to join that App as a replica.
If the app URI has no host address, or is the same as the address of the running host, the host will serve a single replica of a new app.
Watch out for versioning issues! In production, it’s best to end your app URI with a version number which you can update in order to release a new, non-backwards-compatible version with different data and methods. We are attempting to find a solution to this and will be released at a future time.
Object orentation
One of TinyChain’s most powerful features is its object-oriented API.
You can use this to define your own classes, which must inherit from exactly one class, which ultimately inherits from a native class.
For example:
import tinychain as tc
URI = tc.URI("http://example.com/app/area") # <-- edit this
# Specifying `metaclass=tc.Meta` provides JSON encoding functionality for user-defined classes.
# It's only required when subclassing a native class -- subclasses of `Distance` automatically inherit its metaclass.
class Distance(tc.Number, metaclass=tc.Meta):
__uri__ = URI.append("Distance")
@tc.get
def to_feet(self) -> Feet:
return tc.error.NotImplemented("abstract")
@tc.get
def to_meters(self) -> Meters:
return tc.error.NotImplemented("abstract")
class Feet(Distance):
__uri__ = URI.append("Feet")
@tc.get
def to_feet(self) -> Feet:
return self
@tc.get
def to_meters(self) -> Meters:
return self / 3.28
class Meters(Distance):
__uri__ = URI.append("Meters")
@tc.get
def to_feet(self) -> Feet:
return self * 3.28
@tc.get
def to_meters(self) -> Meters:
return self
TinyChain does not have any concept of member visibility, like a “public” or “private” method.
This is because TinyChain objects are meant to be sent over the network and used by client code, making a “private” method is meaningless (and deceptive to the developer implementing it).
If you want to hide an implementation detail from the public API of your class, consider using a helper function outside your class definition.
host your service
Now that we've defined some classes in and a Chain in ...(link to chain docs), it's time to put our service online! You can do this using the same object-oriented API that you used to build the service. For security reasons, TinyChain requires that you load your Cluster configuration from a local file on the host machine; see the next section, for instructions.
from __future__ import annotations
import tinychain as tc
URI = tc.URI("http://127.0.0.1:8702/demo")
class User(tc.app.Model):
__uri__ = URI.append("user")
username = tc.Column("username", tc.String, 100)
def __init__(self, username):
self.username = username
class UserService(tc.graph.Graph):
__uri__ = URI
@tc.post
def create_user(self, new_user: User) -> tc.Number:
user_id = self.user.max_id() + 1
return tc.After(self.user.insert([user_id], [new_user.username]), user_id)
def start_host(name, apps):
# I intend to manually kbuild this out and not use the tests code. Once I publish.
from tests.tctest.process import start_local_host, start_docker
# return start_local_host(name, apps)
return start_docker(name, apps)
if __name__ == "__main__":
# start a new TinyChain host.
host = start_host("demo", [UserService(models=[User])])
# verify that it works as expected
user_id = host.post("/demo/create_user", {"username": "user"})
print(user_id)
assert user_id > 0
You can see more in-depth examples in the tests directory.
With this one I think there is potentially a bug in tinychain?, every time I run the code using the latest tinychain bin (0.9.0-beta) i get the following:
start host process on port 8702
bin/tinychain: error while loading shared libraries: libaf.so.3: cannot open shared object file: No such file or directory
Traceback (most recent call last):
File "/usr/lib/python3.10/runpy.py", line 196, in _run_module_as_main
return _run_code(code, main_globals, None,
File "/usr/lib/python3.10/runpy.py", line 86, in _run_code
exec(code, run_globals)
File "/home/cormac/workspace/python/tinychain/script.py", line 25, in <module>
start_host("demo", [Demo()])
File "/home/cormac/workspace/python/tinychain/script.py", line 19, in start_host
return start_local_host(name, apps)
File "/home/cormac/workspace/python/tinychain/tests/tctest/process.py", line 206, in start_local_host
process.start(wait_time)
File "/home/cormac/workspace/python/tinychain/tests/tctest/process.py", line 141, in start
raise RuntimeError(f"TinyChain process crashed on startup")
RuntimeError: TinyChain process crashed on startup
Note that running it with the docker host is fine and works as expected.
Also currently won't work because of issue: #175
readthedocs.io also has not updated since v0.4
The readthedocs.io issue is now fixed: https://tinychain.readthedocs.io/en/latest/