Skip to content

Commit

Permalink
Merge 071ad19 into 10a50f6
Browse files Browse the repository at this point in the history
  • Loading branch information
icgood committed May 11, 2021
2 parents 10a50f6 + 071ad19 commit 0d8adb1
Show file tree
Hide file tree
Showing 8 changed files with 40 additions and 32 deletions.
17 changes: 0 additions & 17 deletions .vscode/settings.json

This file was deleted.

6 changes: 4 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,8 +36,10 @@ $ swim-protocol-demo -c --name 127.0.0.1:2003 --peer 127.0.0.1:2001 --metadata n
$ swim-protocol-demo -c --name 127.0.0.1:2004 --peer 127.0.0.1:2003 --metadata name four
```

Every 10 seconds or so, each member will randomize its `token` metadata field,
which should be disseminated across the cluster with [eventual consistency][6].
Typing in any window will disseminate what has been typed across the cluster
with [eventual consistency][6].

![swim-protocol-demo](https://user-images.githubusercontent.com/438413/117894784-16580e80-b28b-11eb-9903-762fff92eaf7.gif)

### Getting Started

Expand Down
6 changes: 3 additions & 3 deletions docs/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -129,9 +129,9 @@ Glossary
:term:`gossip` is new enough to be applied or disseminated.

demo
The included `demo`_ is designed to randomize metadata changes on an
interval to see them disseminated across the cluster, as well as watch as
:term:`member` statuses change as demo instances are stopped and started.
The included `demo`_ is designed to show typing being disseminated across
the cluster, as well as watch as :term:`member` statuses change as demo
instances are stopped and started.

.. _SWIM: https://www.cs.cornell.edu/projects/Quicksilver/public_pdfs/SWIM.pdf
.. _Serf: https://www.serf.io/docs/internals/gossip.html
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
license = f.read()

setup(name='swim-protocol',
version='0.3.6',
version='0.3.7',
author='Ian Good',
author_email='ian@icgood.net',
description='SWIM protocol implementation for exchanging cluster '
Expand Down
3 changes: 1 addition & 2 deletions swimprotocol/demo/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,8 +34,7 @@ def main() -> int:
group.add_argument('-c', '--curses', action='store_true',
help='Enable the curses display.')
group.add_argument('-i', '--token-interval', metavar='SECONDS',
type=float, default=10.0,
help='Cluster member token update interval.')
type=float, help='Randomize metadata on an interval.')

args = parser.parse_args()

Expand Down
10 changes: 6 additions & 4 deletions swimprotocol/demo/changes.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
import random
import uuid
from contextlib import AsyncExitStack
from typing import NoReturn
from typing import Optional, NoReturn

from ..members import Members

Expand All @@ -23,8 +23,10 @@ async def _randomize_local(members: Members, interval: float) -> NoReturn:
await asyncio.sleep(sleep_sec)


def change_metadata(members: Members, interval: float) -> AsyncExitStack:
def change_metadata(members: Members, interval: Optional[float]) \
-> AsyncExitStack:
exit_stack = AsyncExitStack()
task = asyncio.create_task(_randomize_local(members, interval))
exit_stack.callback(task.cancel)
if interval is not None:
task = asyncio.create_task(_randomize_local(members, interval))
exit_stack.callback(task.cancel)
return exit_stack
25 changes: 23 additions & 2 deletions swimprotocol/demo/screen.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

import asyncio
import curses
import string
from contextlib import AsyncExitStack
from curses import wrapper
from threading import Event, Condition
Expand All @@ -14,6 +15,12 @@
__all__ = ['run_screen']


def _is_printable(ch: int) -> bool:
return ch >= 0 and ch < 256 \
and ch in string.printable.encode('ascii') \
and ch not in set(b'\t\r\n\x0b\x0c')


class Screen:

def __init__(self, members: Members) -> None:
Expand Down Expand Up @@ -71,6 +78,11 @@ def _render(self, stdscr: Any) -> None:
available = len(self.members.get_status(Status.AVAILABLE)) + 1
stdscr.addstr(f'{available}', curses.A_BOLD)

def _set_typed(self, typed: bytes) -> None:
members = self.members
new_metadata = dict(members.local.metadata) | {'typed': typed}
members.update(members.local, new_metadata=new_metadata)

def main(self, stdscr: Any) -> None:
curses.cbreak()
curses.use_default_colors()
Expand All @@ -84,12 +96,21 @@ def main(self, stdscr: Any) -> None:
curses.init_pair(8, curses.COLOR_RED, -1)
curses.curs_set(0)
stdscr.clear()
stdscr.timeout(0)
typed = b''
while not self.done.is_set():
stdscr.clear()
self._render(stdscr)
stdscr.refresh()
with self.ready:
self.ready.wait(timeout=1.0)
for i in range(20):
with self.ready:
if self.ready.wait(timeout=0.05):
break
ch = stdscr.getch()
if _is_printable(ch):
typed += bytes([ch])
typed = typed[-30:]
self._set_typed(typed)

async def run_thread(self) -> None:
await asyncio.to_thread(wrapper, self.main)
Expand Down
3 changes: 2 additions & 1 deletion swimprotocol/members.py
Original file line number Diff line number Diff line change
Expand Up @@ -105,7 +105,8 @@ def _set_status(self, status: Status) -> None:
def _set_metadata(self, metadata: Mapping[str, bytes]) -> None:
assert self._pending_metadata is None
pending_metadata = frozenset(metadata.items())
if pending_metadata != self._metadata:
if self._metadata_dict is self.METADATA_UNKNOWN or \
pending_metadata != self._metadata:
self._pending_metadata = pending_metadata

def _save(self, source: Optional[Member], next_clock: int) -> bool:
Expand Down

0 comments on commit 0d8adb1

Please sign in to comment.