Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
  • Loading branch information
jgoteam committed May 3, 2024
2 parents c751ff2 + 13f2da0 commit c3857ec
Show file tree
Hide file tree
Showing 7 changed files with 333 additions and 324 deletions.
44 changes: 22 additions & 22 deletions src/components/Diagrams/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -98,26 +98,26 @@ export const OptimisticUI = () => {

export const NewClientConnection = () => {
return (
<figure>
<figure className="mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-new-client-connection.svg"
className="w-1/2"
></object>
<figcaption></figcaption>
<figcaption className="-mt-14">A new client connects, receives a copy of the document from the server</figcaption>
</figure>
)
}

export const WhiteboardConflict = () => {
return (
<figure>
<figure className="mb-14">
<object
type="image/svg+xml"
data="/img/diagrams/diag-whiteboard-conflict.svg"
className="w-full"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">Concurrent edits can lead to conflicting state</figcaption>
</figure>
)
}
Expand Down Expand Up @@ -202,26 +202,26 @@ export const OT = () => {

export const SyncingModel1 = () => {
return (
<figure className="mt-8 mb-8">
<figure className="mt-8 mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-syncingModel-1.svg"
className="w-4/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">All local changes are saved in a pending queue</figcaption>
</figure>
)
}

export const SyncingModel3 = () => {
return (
<figure className="mt-8 mb-8">
<figure className="mt-8 mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-syncingModel-3.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">Local changes are sent to the server, and removed from the pending queue when confirmed</figcaption>
</figure>
)
}
Expand All @@ -234,7 +234,7 @@ export const SyncingModel4 = () => {
data="/img/diagrams/diag-syncingModel-4.svg"
className="w-full"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">Authoritative updates are sent to all connected clients</figcaption>
</figure>
)
}
Expand All @@ -260,33 +260,33 @@ export const CloudflareArchitecture = () => {
data="/img/diagrams/diag-cloudflare-architecture.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption>New Durable Objects are created on demand, allowing near limitless scaling</figcaption>
</figure>
)
}

export const StateUpdates = () => {
return (
<figure className="mt-6 mb-6">
<figure className="mt-6 mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-StateUpdates.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-6">With each sever update, the entire dataset is sent to the client</figcaption>
</figure>
)
}

export const DeltaUpdate = () => {
return (
<figure className="mt-6 mb-6">
<figure className="mt-6 mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-DeltaUpdates.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-6">With delta updates, only the changes are sent to the client</figcaption>
</figure>
)
}
Expand All @@ -299,7 +299,7 @@ export const SnapshotID = () => {
data="/img/diagrams/diag-snapshotId.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption>The client checks the `snapshotID` for every update it receives</figcaption>
</figure>
)
}
Expand All @@ -312,20 +312,20 @@ export const ON2Messaging = () => {
data="/img/diagrams/diag-ON2-messaging.svg"
className="w-10/12"
></object>
<figcaption></figcaption>
<figcaption>Each client message received results in a full broadcast to all clients</figcaption>
</figure>
)
}

export const TimeDrivenMessages = () => {
return (
<figure>
<figure className="mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-timeDrivenMessages.svg"
className="w-10/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">The server collates all updates received within a specified time interval, and broadcasts them all in a single update </figcaption>
</figure>
)
}
Expand All @@ -338,20 +338,20 @@ export const ONMessaging = () => {
data="/img/diagrams/diag-ON-messaging.svg"
className="w-10/12"
></object>
<figcaption></figcaption>
<figcaption>Client messages are collated based on a time interval, greatly reducing how many messages are sent by the server</figcaption>
</figure>
)
}

export const Subscriptions = () => {
return (
<figure className="mb-6">
<figure className="mb-12">
<object
type="image/svg+xml"
data="/img/diagrams/diag-Subscriptions.svg"
className="w-10/12"
></object>
<figcaption></figcaption>
<figcaption className="-mt-8">Subscriptions create a link between specific React components and their respective data on the server</figcaption>
</figure>
)
}
Expand All @@ -364,7 +364,7 @@ export const DashboardArchitecture = () => {
data="/img/diagrams/diag-Dashboard-Architecture.svg"
className="w-8/12"
></object>
<figcaption></figcaption>
<figcaption>Both client app and express backend run locally</figcaption>
</figure>
)
}
19 changes: 12 additions & 7 deletions src/pages/case-study.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ Since the advent of Google Docs, the ability for multiple clients to simultaneou

<WhiteboardConflict />

If these changes occur simultaneously, a conflict clearly occurs and to maintain a consistent, synchronized view across clients (i.e. state convergence), there must be some kind of conflict-resolution strategy in place
If these changes occur simultaneously, a conflict clearly occurs and to maintain a consistent, synchronized view across clients (i.e. state convergence), there must be some kind of conflict-resolution strategy in place.

#### Conflict Resolution Strategies

Expand All @@ -237,17 +237,17 @@ However, if a change is meant to be [deterministic](https://en.wikipedia.org/wik

The process of transactional conflict resolution is somewhat simple to reason about.

If two clients make a concurrent change to the same object but modify a different property, no conflicts occur. Because clients only send the intent of a change, these can both be processed in the order of arrival by the server
If two clients make a concurrent change to the same object but modify a different property, no conflicts occur. Because clients only send the intent of a change, these can both be processed in the order of arrival by the server.

<NoConflictEdits />

When concurrent changes occur to the same property, a conflict occurs. By default, the server resolves this conflict using a simple [Last Write Wins](https://dzone.com/articles/conflict-resolution-using-last-write-wins-vs-crdts) (LWW) approach. The server then broadcasts the resolved state to all clients.

<ConflictEdits />

However, depending on the application, it is possible to build in any custom conflict resolution that would override the default Last Write Wins Behavior
However, depending on the application, it is possible to build in any custom conflict resolution that would override the default Last Write Wins Behavior.

While this strategy may not be best suited for use cases where LLW is not the desired default resolution strategy or for decentralized architectures, it is highly flexible and easy to reason about
While this strategy may not be best suited for use cases where LLW is not the desired default resolution strategy or for decentralized architectures, it is highly flexible and easy to reason about.

##### Conflict-Free Replicated Data Types (CRDTs)

Expand Down Expand Up @@ -365,8 +365,8 @@ Next one can choose to add Syncosaurus to an existing React project using `npx s

<img
src="/img/screenshots/syncosaurus-init.png"
style={{ transform: 'scale(.82)', borderRadius: '0.5rem' }}>
</img>
style={{ transform: 'scale(.82)', borderRadius: '0.5rem' }}
></img>

#### Create and Launch

Expand Down Expand Up @@ -562,7 +562,12 @@ The dashboard includes hourly time-series metrics related to errors and usage fo
src="/img/screenshots/dashboard_screenshot.png"
alt="dashboard screenshot"
width="85%"
style={{ transform: 'scale(.82)', borderRadius: '0.5rem', boxShadow: '0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)' }}
style={{
transform: 'scale(.82)',
borderRadius: '0.5rem',
boxShadow:
'0 4px 6px -1px rgb(0 0 0 / 0.1), 0 2px 4px -2px rgb(0 0 0 / 0.1)',
}}
/>
</figure>

Expand Down
278 changes: 138 additions & 140 deletions static/img/diagrams/diag-CRDT.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
20 changes: 8 additions & 12 deletions static/img/diagrams/diag-Dashboard-Architecture.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
222 changes: 111 additions & 111 deletions static/img/diagrams/diag-OT.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit c3857ec

Please sign in to comment.