Skip to content

Commit

Permalink
docs additions
Browse files Browse the repository at this point in the history
  • Loading branch information
hpx7 committed Oct 11, 2021
1 parent 621146b commit cebc350
Show file tree
Hide file tree
Showing 2 changed files with 24 additions and 7 deletions.
9 changes: 9 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,6 +114,15 @@ Finally, we can see our working application in action:

![image](https://user-images.githubusercontent.com/5400947/134372344-6b4ed46c-feed-4776-95f8-9d0499570b76.png)

Here are some example apps built with rtag:

- [avalon](examples/avalon)
- [chess](examples/chess)
- [codenames](examples/codenames)
- [poker](examples/poker)
- [rock-paper-scissor](examples/rock-paper-scissor)
- [uno](examples/uno)

For more examples, check out the [examples directory](https://github.com/hpx7/rtag/tree/develop/examples).

## Additional resources
Expand Down
22 changes: 15 additions & 7 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,28 @@ The primary goal of rtag is to offer the simplest development experience possibl

## Type driven development

By encoding the API in the `rtag.yml` upfront, rtag is given a lot of information about how the application functions. It then tries to use this information to help the developer as much as possible, by generating (1) typesafe clients with the method calls and types built in, (2) the server interface which the implmentation needs to implement, and (3) a debug application which allows extremely fast prototyping and testing.
By encoding the API in the `rtag.yml` upfront, rtag is given a lot of information about how the application functions. It then tries to use this information to help the developer as much as possible, by generating

1. typesafe clients with the method calls and types built in
2. the server interface which the implmentation needs to implement
3. a debug application which allows extremely fast prototyping and testing

## Core loop

1. clients call methods, server runs `onTick`
2. state is mutated inside methods/`onTick`
3. changes are picked up by framework via change detection
4. updates are broadcasted via `getUserState`
rtag applications consist of a set of independent "states", each of which represent a new instance of the application.

First, clients initialize a new state via the `initialize` method. Then the state evolves over time with this lifecycle:

1. clients call methods to modify the state
2. the server validates the method calls and if valid, mutates the state
3. changes to the state are automatically picked up by the framework
4. the server obtains new user states per client via `getUserState` and broadcasts updates

## Replay log

rtag models the backend as a deterministic state machine. Internal state is modified determinsitically as a function of its inputs. If we write down the method + its inputs every time we detect a modification, we can later reconstruct the state by replaying all the method calls sequentially.
rtag models the backend as a deterministic state machine. Internal state is modified determinsitically as a function of its inputs. If we write down the method name and its inputs every time state is modified, we can later reconstruct the state by replaying all the method calls sequentially.

There are a few common sources of non-determinism that often live in server side logic: (pseudo-)random numbers, current time, and api calls. To still be able to determinsitically reconstruct the state while still allowing for these sources, rtag passes in a `context` object as an argument to methods/`onTick`. By utilizing the functions on this object (e.g. `context.time()`), rtag is able to write down the appropriate information in the replay log so that it can feed in the same values during replay time.
There are a few common sources of non-determinism that often live in server side logic: (pseudo-)random numbers, current time, and api calls. To still be able to determinsitically reconstruct the state while still allowing for these sources, rtag passes in a `context` object as an argument to methods/`onTick`. By utilizing the functions on this object (e.g. `ctx.time()`), rtag is able to write down the appropriate information in the replay log so that it can feed in the same values during replay time.

The alternative to this approach is to write down full state snapshots instead. However, if the state is large, this can be quite slow, reducing the frequency at which state snapshots can be written. In contrast, method inputs will typically be very small and thus writing them down will be very fast. The other disadvantage of writing state snapshots is that it is required for the internal state to be serializable. With the replay log approach, you can use e.g. libraries with hidden state and not worry how they serialize!

Expand Down

0 comments on commit cebc350

Please sign in to comment.