Skip to content

Commit

Permalink
deploy: 883dda8
Browse files Browse the repository at this point in the history
  • Loading branch information
Askaholic committed Oct 22, 2023
1 parent 8a29a01 commit 47e5319
Show file tree
Hide file tree
Showing 32 changed files with 2,014 additions and 503 deletions.
80 changes: 42 additions & 38 deletions asyncio_extensions.html
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,10 @@ <h1 class="title">Module <code>server.asyncio_extensions</code></h1>
AsyncContextManager,
Callable,
Coroutine,
Iterable,
Optional,
Protocol,
TypeVar,
cast,
overload
)
Expand All @@ -51,6 +53,7 @@ <h1 class="title">Module <code>server.asyncio_extensions</code></h1>

AsyncFunc = Callable[..., Coroutine[Any, Any, Any]]
AsyncDecorator = Callable[[AsyncFunc], AsyncFunc]
T = TypeVar(&#34;T&#34;)


class AsyncLock(Protocol, AsyncContextManager[&#34;AsyncLock&#34;]):
Expand All @@ -59,23 +62,24 @@ <h1 class="title">Module <code>server.asyncio_extensions</code></h1>
def release(self) -&gt; None: ...


async def gather_without_exceptions(
tasks: list[asyncio.Task],
*exceptions: type[BaseException],
) -&gt; list[Any]:
&#34;&#34;&#34;
Run coroutines in parallel, raising the first exception that dosen&#39;t
match any of the specified exception classes.
&#34;&#34;&#34;
results = []
for fut in asyncio.as_completed(tasks):
try:
results.append(await fut)
except exceptions:
logger.debug(
&#34;Ignoring error in gather_without_exceptions&#34;, exc_info=True
async def map_suppress(
func: Callable[[T], Coroutine[Any, Any, Any]],
iterable: Iterable[T],
logger: logging.Logger = logger,
msg: str = &#34;&#34;
):
results = await asyncio.gather(
*(func(item) for item in iterable),
return_exceptions=True
)
for result, item in zip(results, iterable):
if isinstance(result, BaseException):
logger.exception(
&#34;Unexpected error %s%s&#34;,
msg,
item,
exc_info=result
)
return results


# Based on python3.8 asyncio.Lock
Expand Down Expand Up @@ -239,33 +243,33 @@ <h1 class="title">Module <code>server.asyncio_extensions</code></h1>
<section>
<h2 class="section-title" id="header-functions">Functions</h2>
<dl>
<dt id="server.asyncio_extensions.gather_without_exceptions"><code class="name flex">
<span>async def <span class="ident">gather_without_exceptions</span></span>(<span>tasks: list[_asyncio.Task], *exceptions: type[BaseException]) ‑> list[typing.Any]</span>
<dt id="server.asyncio_extensions.map_suppress"><code class="name flex">
<span>async def <span class="ident">map_suppress</span></span>(<span>func: Callable[[~T], Coroutine[Any, Any, Any]], iterable: Iterable[~T], logger: logging.Logger = &lt;Logger server.asyncio_extensions (WARNING)&gt;, msg: str = '')</span>
</code></dt>
<dd>
<div class="desc"><p>Run coroutines in parallel, raising the first exception that dosen't
match any of the specified exception classes.</p></div>
<div class="desc"></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">async def gather_without_exceptions(
tasks: list[asyncio.Task],
*exceptions: type[BaseException],
) -&gt; list[Any]:
&#34;&#34;&#34;
Run coroutines in parallel, raising the first exception that dosen&#39;t
match any of the specified exception classes.
&#34;&#34;&#34;
results = []
for fut in asyncio.as_completed(tasks):
try:
results.append(await fut)
except exceptions:
logger.debug(
&#34;Ignoring error in gather_without_exceptions&#34;, exc_info=True
)
return results</code></pre>
<pre><code class="python">async def map_suppress(
func: Callable[[T], Coroutine[Any, Any, Any]],
iterable: Iterable[T],
logger: logging.Logger = logger,
msg: str = &#34;&#34;
):
results = await asyncio.gather(
*(func(item) for item in iterable),
return_exceptions=True
)
for result, item in zip(results, iterable):
if isinstance(result, BaseException):
logger.exception(
&#34;Unexpected error %s%s&#34;,
msg,
item,
exc_info=result
)</code></pre>
</details>
</dd>
<dt id="server.asyncio_extensions.synchronized"><code class="name flex">
Expand Down Expand Up @@ -552,7 +556,7 @@ <h1>Index</h1>
</li>
<li><h3><a href="#header-functions">Functions</a></h3>
<ul class="">
<li><code><a title="server.asyncio_extensions.gather_without_exceptions" href="#server.asyncio_extensions.gather_without_exceptions">gather_without_exceptions</a></code></li>
<li><code><a title="server.asyncio_extensions.map_suppress" href="#server.asyncio_extensions.map_suppress">map_suppress</a></code></li>
<li><code><a title="server.asyncio_extensions.synchronized" href="#server.asyncio_extensions.synchronized">synchronized</a></code></li>
<li><code><a title="server.asyncio_extensions.synchronizedmethod" href="#server.asyncio_extensions.synchronizedmethod">synchronizedmethod</a></code></li>
</ul>
Expand Down
142 changes: 137 additions & 5 deletions broadcast_service.html
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,10 @@ <h1 class="title">Module <code>server.broadcast_service</code></h1>
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">from aio_pika import DeliveryMode
<pre><code class="python">import asyncio

import humanize
from aio_pika import DeliveryMode

from .config import config
from .core import Service
Expand Down Expand Up @@ -55,13 +58,14 @@ <h1 class="title">Module <code>server.broadcast_service</code></h1>
self.message_queue_service = message_queue_service
self.game_service = game_service
self.player_service = player_service
self._report_dirties_event = None

async def initialize(self):
# Using a lazy interval timer so that the intervals can be changed
# without restarting the server.
self._broadcast_dirties_timer = LazyIntervalTimer(
lambda: config.DIRTY_REPORT_INTERVAL,
self.report_dirties,
self._monitored_report_dirties,
start=True
)
self._broadcast_ping_timer = LazyIntervalTimer(
Expand All @@ -70,6 +74,14 @@ <h1 class="title">Module <code>server.broadcast_service</code></h1>
start=True
)

async def _monitored_report_dirties(self):
event = asyncio.Event()
self._report_dirties_event = event
try:
await self.report_dirties()
finally:
event.set()

async def report_dirties(self):
&#34;&#34;&#34;
Send updates about any dirty (changed) entities to connected players.
Expand Down Expand Up @@ -143,7 +155,52 @@ <h1 class="title">Module <code>server.broadcast_service</code></h1>
)

def broadcast_ping(self):
self.server.write_broadcast({&#34;command&#34;: &#34;ping&#34;})</code></pre>
self.server.write_broadcast({&#34;command&#34;: &#34;ping&#34;})

async def wait_report_dirtes(self):
&#34;&#34;&#34;
Wait for the current report_dirties task to complete.
&#34;&#34;&#34;
if self._report_dirties_event is None:
return

await self._report_dirties_event.wait()

async def graceful_shutdown(self):
if config.SHUTDOWN_KICK_IDLE_PLAYERS:
message = (
&#34;If you&#39;re in a game you can continue to play, otherwise you &#34;
&#34;will be disconnected. If you aren&#39;t reconnected automatically &#34;
&#34;please wait a few minutes and try to connect again.&#34;
)
else:
message = (
&#34;If you&#39;re in a game you can continue to play, however, you &#34;
&#34;will not be able to create any new games until the server has &#34;
&#34;been restarted.&#34;
)

delta = humanize.precisedelta(config.SHUTDOWN_GRACE_PERIOD)
self.server.write_broadcast({
&#34;command&#34;: &#34;notice&#34;,
&#34;style&#34;: &#34;info&#34;,
&#34;text&#34;: (
f&#34;The server will be shutting down for maintenance in {delta}! &#34;
f&#34;{message}&#34;
)
})

async def shutdown(self):
self.server.write_broadcast({
&#34;command&#34;: &#34;notice&#34;,
&#34;style&#34;: &#34;info&#34;,
&#34;text&#34;: (
&#34;The server has been shut down for maintenance &#34;
&#34;but should be back online soon. If you experience any &#34;
&#34;problems, please restart your client. &lt;br/&gt;&lt;br/&gt;&#34;
&#34;We apologize for this interruption.&#34;
)
})</code></pre>
</details>
</section>
<section>
Expand Down Expand Up @@ -182,13 +239,14 @@ <h2 class="section-title" id="header-classes">Classes</h2>
self.message_queue_service = message_queue_service
self.game_service = game_service
self.player_service = player_service
self._report_dirties_event = None

async def initialize(self):
# Using a lazy interval timer so that the intervals can be changed
# without restarting the server.
self._broadcast_dirties_timer = LazyIntervalTimer(
lambda: config.DIRTY_REPORT_INTERVAL,
self.report_dirties,
self._monitored_report_dirties,
start=True
)
self._broadcast_ping_timer = LazyIntervalTimer(
Expand All @@ -197,6 +255,14 @@ <h2 class="section-title" id="header-classes">Classes</h2>
start=True
)

async def _monitored_report_dirties(self):
event = asyncio.Event()
self._report_dirties_event = event
try:
await self.report_dirties()
finally:
event.set()

async def report_dirties(self):
&#34;&#34;&#34;
Send updates about any dirty (changed) entities to connected players.
Expand Down Expand Up @@ -270,7 +336,52 @@ <h2 class="section-title" id="header-classes">Classes</h2>
)

def broadcast_ping(self):
self.server.write_broadcast({&#34;command&#34;: &#34;ping&#34;})</code></pre>
self.server.write_broadcast({&#34;command&#34;: &#34;ping&#34;})

async def wait_report_dirtes(self):
&#34;&#34;&#34;
Wait for the current report_dirties task to complete.
&#34;&#34;&#34;
if self._report_dirties_event is None:
return

await self._report_dirties_event.wait()

async def graceful_shutdown(self):
if config.SHUTDOWN_KICK_IDLE_PLAYERS:
message = (
&#34;If you&#39;re in a game you can continue to play, otherwise you &#34;
&#34;will be disconnected. If you aren&#39;t reconnected automatically &#34;
&#34;please wait a few minutes and try to connect again.&#34;
)
else:
message = (
&#34;If you&#39;re in a game you can continue to play, however, you &#34;
&#34;will not be able to create any new games until the server has &#34;
&#34;been restarted.&#34;
)

delta = humanize.precisedelta(config.SHUTDOWN_GRACE_PERIOD)
self.server.write_broadcast({
&#34;command&#34;: &#34;notice&#34;,
&#34;style&#34;: &#34;info&#34;,
&#34;text&#34;: (
f&#34;The server will be shutting down for maintenance in {delta}! &#34;
f&#34;{message}&#34;
)
})

async def shutdown(self):
self.server.write_broadcast({
&#34;command&#34;: &#34;notice&#34;,
&#34;style&#34;: &#34;info&#34;,
&#34;text&#34;: (
&#34;The server has been shut down for maintenance &#34;
&#34;but should be back online soon. If you experience any &#34;
&#34;problems, please restart your client. &lt;br/&gt;&lt;br/&gt;&#34;
&#34;We apologize for this interruption.&#34;
)
})</code></pre>
</details>
<h3>Ancestors</h3>
<ul class="hlist">
Expand Down Expand Up @@ -376,11 +487,31 @@ <h3>Methods</h3>
)</code></pre>
</details>
</dd>
<dt id="server.broadcast_service.BroadcastService.wait_report_dirtes"><code class="name flex">
<span>async def <span class="ident">wait_report_dirtes</span></span>(<span>self)</span>
</code></dt>
<dd>
<div class="desc"><p>Wait for the current report_dirties task to complete.</p></div>
<details class="source">
<summary>
<span>Expand source code</span>
</summary>
<pre><code class="python">async def wait_report_dirtes(self):
&#34;&#34;&#34;
Wait for the current report_dirties task to complete.
&#34;&#34;&#34;
if self._report_dirties_event is None:
return

await self._report_dirties_event.wait()</code></pre>
</details>
</dd>
</dl>
<h3>Inherited members</h3>
<ul class="hlist">
<li><code><b><a title="server.core.service.Service" href="core/service.html#server.core.service.Service">Service</a></b></code>:
<ul class="hlist">
<li><code><a title="server.core.service.Service.graceful_shutdown" href="core/service.html#server.core.service.Service.graceful_shutdown">graceful_shutdown</a></code></li>
<li><code><a title="server.core.service.Service.initialize" href="core/service.html#server.core.service.Service.initialize">initialize</a></code></li>
<li><code><a title="server.core.service.Service.on_connection_lost" href="core/service.html#server.core.service.Service.on_connection_lost">on_connection_lost</a></code></li>
<li><code><a title="server.core.service.Service.shutdown" href="core/service.html#server.core.service.Service.shutdown">shutdown</a></code></li>
Expand Down Expand Up @@ -409,6 +540,7 @@ <h4><code><a title="server.broadcast_service.BroadcastService" href="#server.bro
<ul class="">
<li><code><a title="server.broadcast_service.BroadcastService.broadcast_ping" href="#server.broadcast_service.BroadcastService.broadcast_ping">broadcast_ping</a></code></li>
<li><code><a title="server.broadcast_service.BroadcastService.report_dirties" href="#server.broadcast_service.BroadcastService.report_dirties">report_dirties</a></code></li>
<li><code><a title="server.broadcast_service.BroadcastService.wait_report_dirtes" href="#server.broadcast_service.BroadcastService.wait_report_dirtes">wait_report_dirtes</a></code></li>
</ul>
</li>
</ul>
Expand Down
Loading

0 comments on commit 47e5319

Please sign in to comment.