diff --git a/.claude/rules/python-annotate-every-parameter.md b/.claude/rules/python-annotate-every-parameter.md new file mode 100644 index 000000000..e61c7b800 --- /dev/null +++ b/.claude/rules/python-annotate-every-parameter.md @@ -0,0 +1,21 @@ +# Annotate every Python parameter and return type + +Give every parameter of every Python function and method a type +annotation, and every function a return type — including `self`-less +helpers, nested functions, and parameters whose type feels obvious +from the name. Leaving one off because `mypy` doesn't demand it is +not a reason to leave it off. + +**Why:** `mypy` only checks a function's body once its signature is +annotated, so a single un-annotated parameter silently switches off +checking for everything that flows through it. An annotation is also +the cheapest documentation a reader gets: `stub` says nothing, +`stub: react_pb2_grpc.ReactStub` says where to look next. + +**How to apply:** When writing or editing a `def`, annotate all of +its parameters and its return type in the same edit. When a +parameter's type is a generated protobuf message or gRPC stub, name +that type rather than falling back to `Any` — import it if the module +doesn't already. `self` and `cls` need no annotation, and neither do +`*args`/`**kwargs` when they are forwarded verbatim to an already +typed callee. diff --git a/rbt/v1alpha1/options.proto b/rbt/v1alpha1/options.proto index 592b580d5..82f1fe423 100644 --- a/rbt/v1alpha1/options.proto +++ b/rbt/v1alpha1/options.proto @@ -17,6 +17,13 @@ message ReaderMethodOptions { STREAMING = 2; } State state = 3; + + // Whether the server warns, in its log, every time a client of a + // reactive read of this method falls behind and has updates skipped + // for it. Unset means yes. A method whose readers only ever want + // its latest state, so that skipping the states in between is the + // point, sets this to `false`. + optional bool warn_on_flow_control = 4; } message WriterMethodOptions { diff --git a/rbt/v1alpha1/react.proto b/rbt/v1alpha1/react.proto index 0b770b655..41621fb0f 100644 --- a/rbt/v1alpha1/react.proto +++ b/rbt/v1alpha1/react.proto @@ -18,6 +18,25 @@ message QueryRequest { // Authorization bearer token. optional string bearer_token = 3; + + // Whether this client tells us which responses it has processed, + // so that we can stay at most a bounded number of responses ahead + // of it. A client that does not set this gets responses at whatever + // rate we produce them, whether or not it can consume them that + // fast. + bool client_continues_query = 4; + + // Sequence number of the last `QueryResponse` this client has fully + // processed, which returns to the server the right to send that + // many more; see `Query`. This is how a client whose responses + // arrive over a websocket continues its query, on that same + // websocket, and it is the only way that works for such a client. + // Only meaningful on transports where a client can send more than + // one message per query, i.e. websockets. When this is set the + // other fields are ignored. A heartbeat is an otherwise empty + // `QueryRequest`, which is why presence matters here: sequence + // number zero is a real response. + optional uint64 continue_query_sequence_number = 5; } message QueryResponse { @@ -40,8 +59,46 @@ message QueryResponse { // // TODO(benh): send these as bytes? repeated string idempotency_keys = 2; + + // Unique ID of the query this response belongs to, which a client + // names when it continues that query. The same for every response + // of one `Query`. Only set when the client set + // `client_continues_query` on its `QueryRequest`; when unset, the + // client is not expected to continue anything. + optional string query_id = 4; + + // Position of this response within its query, counting from zero. + // A client names the last one it has fully processed to continue + // the query; see `Query`. + uint64 sequence_number = 5; + + // How long this response waited for the client to make room for it, + // and how many updates were merged into it while it waited. Both + // are zero for a client that kept up. A client that finds them set + // is one whose user saw a stale screen for that long, and which + // missed that many updates on the way to the state this response + // carries; see `Query`. + uint32 stall_milliseconds = 6; + uint32 skipped_updates = 7; +} + +//////////////////////////////////////////////////////////////////////// + +message ContinueQueryRequest { + // ID of the query being continued, from `QueryResponse.query_id`. + string query_id = 1; + + // Sequence number of the last `QueryResponse` the client has fully + // processed. The server returns to itself the right to send one + // more response for each response between the last number this + // client named and this one, so a client that processed several + // while a previous `ContinueQuery` was in flight names only the + // newest and is credited for all of them. + uint64 sequence_number = 2; } +message ContinueQueryResponse {} + //////////////////////////////////////////////////////////////////////// // TODO(benh): support batch, e.g., create a `MutateRequests` which @@ -90,8 +147,42 @@ message WebSocketsConnectionResponse {} service React { // Allows users to "watch" the response of a unary reader method for // changes. The current response of the method is sent when the - // stream is opened, then a new response is sent whenever the - // state changes in a way that causes the method's response to change. + // stream is opened. + // + // A client that sets `client_continues_query` is sent responses + // under a window: the server may run up to a fixed number of + // responses ahead of what that client has continued past, and each + // response it sends spends one of them. While the window has + // room the server sends every state change as it happens, so a + // client that keeps up sees every update at the rate they occur. + // Once the window is empty the server holds the response it has + // ready and merges every state that follows into it, so when the + // window reopens the client is sent a single response carrying the + // _latest_ state, with `stall_milliseconds` and `skipped_updates` + // saying how long it waited and how many updates that one response + // stood in for. So a client that keeps up loses nothing, and a + // client that cannot is at most a window behind rather than + // arbitrarily behind. A client that does not set + // `client_continues_query` gets responses at whatever rate the + // server produces them, whether or not it can consume them + // that fast. + // + // To continue a query a client names the sequence number of the + // last response it has fully processed, and the server credits it + // for every response up to that one. A client may therefore process + // several responses while a single `ContinueQuery` is in flight and + // name only the newest. + // + // How a client continues its query is determined by the transport + // its responses arrive on, and only that way works: a client + // reading over a websocket sends a `QueryRequest` with + // `continue_query_sequence_number` set on that same websocket, and + // a client reading over any other transport calls `ContinueQuery`. + // The server tracks each query's window per transport, so one that + // arrives the other way names a query the server has no record of, + // which it ignores: the request is accepted, no room is returned, + // and the query stops producing responses once its window + // empties. // // NOTE: the service name and state ID is expected to be part of the // gRPC metadata, exactly like any other reboot requests. @@ -101,6 +192,20 @@ service React { }; } + // Tells the server which responses from `Query` a client has fully + // processed, returning that much room to the query's window. Must + // be called on the same server that produced those responses. + // + // For a client whose responses arrive over a websocket this is the + // wrong mechanism; such a client continues its query on the + // websocket that carries its responses, by sending a `QueryRequest` + // with `continue_query_sequence_number` set. + rpc ContinueQuery(ContinueQueryRequest) returns (ContinueQueryResponse) { + option (google.api.http) = { + post: "/rbt.v1alpha1.React/ContinueQuery" + }; + } + // All connections must be HTTP/2 (h2), but the WebSocket protocol // is inherently HTTP/1.1. RFC 8441 // (https://datatracker.ietf.org/doc/html/rfc8441) introduced diff --git a/reboot/aio/contexts.py b/reboot/aio/contexts.py index b814275c2..a8fea6812 100644 --- a/reboot/aio/contexts.py +++ b/reboot/aio/contexts.py @@ -342,6 +342,60 @@ def from_grpc_metadata(cls, metadata: GrpcMetadata) -> 'Participants': return participants +class QueryContinuations: + """Calls `React.ContinueQuery` for the responses of a `React.Query` + that a client has fully processed, which is what returns room to + that query's window. + + Keeps at most one call in flight. While one is on its way the + client keeps processing, so the next call names only the newest + response it has handled; the server credits every response up to + that one, so nothing is lost by not naming each individually. + """ + + def __init__( + self, + stub: react_pb2_grpc.ReactStub, + metadata: GrpcMetadata, + ) -> None: + self._stub = stub + self._metadata = metadata + self._continuation: Optional[asyncio.Task] = None + + async def continue_past( + self, + query_response: react_pb2.QueryResponse, + ) -> None: + """Continues the query past `query_response`, if there is no + call already in flight. Raises whatever a previous call raised, + so that a failure to continue surfaces on the read.""" + if not query_response.HasField('query_id'): + # An older backend doesn't send a query ID and doesn't + # expect to be told. + return + + if self._continuation is not None and self._continuation.done(): + await self._continuation + self._continuation = None + + if self._continuation is None: + self._continuation = asyncio.ensure_future( + self._stub.ContinueQuery( + react_pb2.ContinueQueryRequest( + query_id=query_response.query_id, + sequence_number=query_response.sequence_number, + ), + # The same metadata ensures we're routed to the + # same server. + metadata=self._metadata, + ) + ) + + async def stop(self) -> None: + await wait_for_tasks([self._continuation], cancel=True) + self._continuation = None + + class React: """Encapsulates machinery necessary for contexts that are "reactive", aka, those that are initiated from calls to `React.Query` and who @@ -474,7 +528,9 @@ async def query(): self._state_type_name, self._state_ref ) - call = react_pb2_grpc.ReactStub(channel).Query( + stub = react_pb2_grpc.ReactStub(channel) + + call = stub.Query( react_pb2.QueryRequest( method=self._method, request=serialized_request, @@ -497,26 +553,39 @@ async def query(): async def loop(): assert task is not None + # Keep consuming however fast they arrive, + # letting each response replace the one before + # it. A reader that reads faster than this one + # can re-run therefore has its updates + # accumulated into the latest state, which is + # the one waiting here when this reader next + # asks for it. See + # https://github.com/reboot-dev/mono/issues/4754. + # + # Replacing drops the idempotency keys the + # response carried, which is deliberate: the + # keys a reactive read reports upward are the + # ones for its own state's mutations, which + # `reactively()` aggregates for it, and a + # browser observes a mutation on the query of + # the state it mutated. Keys kept here would + # reach no one. async for query_response in call: - if not query_response.HasField('response'): - continue - - response = self._response_type() - response.ParseFromString(query_response.response) - - self._used_response[task].clear() - - self._calls[task] = call + if query_response.HasField('response'): + response = self._response_type() + response.ParseFromString( + query_response.response + ) - self._responses[task] = asyncio.Future() - self._responses[task].set_result(response) + self._calls[task] = call - if not have_first_response.is_set(): - have_first_response.set() - else: - self._event.set() + self._responses[task] = asyncio.Future() + self._responses[task].set_result(response) - await self._used_response[task].wait() + if not have_first_response.is_set(): + have_first_response.set() + else: + self._event.set() raise RuntimeError('React.Query should be infinite') diff --git a/reboot/aio/internals/middleware.py b/reboot/aio/internals/middleware.py index d330a71de..95059a7df 100644 --- a/reboot/aio/internals/middleware.py +++ b/reboot/aio/internals/middleware.py @@ -6,6 +6,7 @@ import uuid from abc import ABC, abstractmethod from contextlib import contextmanager +from google.protobuf import descriptor_pool from google.protobuf.message import Message from logging import Logger from reboot.aio.auth.authorizers import Authorizer @@ -37,6 +38,7 @@ StateRef, StateTypeName, ) +from reboot.options import get_method_options from reboot.settings import DOCS_BASE_URL from reboot.time import DateTimeWithTimeZone from typing import ( @@ -135,6 +137,33 @@ def state_type_name(self) -> StateTypeName: def service_names(self) -> list[ServiceName]: return self._service_names + def warns_on_flow_control(self, method: str) -> bool: + """Whether the server warns every time a client of a reactive + read of `method` falls behind and has updates skipped for it, + which is what the method's `warn_on_flow_control` reader + option decides; a method that has not set it warns.""" + pool = descriptor_pool.Default() + + for service_name in self._service_names: + try: + service = pool.FindServiceByName(service_name) + except KeyError: + continue + + descriptor = service.methods_by_name.get(method) + + if descriptor is None: + continue + + reader = get_method_options(descriptor).reader + + if reader.HasField('warn_on_flow_control'): + return reader.warn_on_flow_control + + return True + + return True + def create_context( self, *, diff --git a/reboot/aio/react.py b/reboot/aio/react.py index d1039e986..12dac4264 100644 --- a/reboot/aio/react.py +++ b/reboot/aio/react.py @@ -2,9 +2,11 @@ import grpc import logging import reboot.aio.placement +import time import traceback import uuid import websockets +from asyncio import CancelledError from google.protobuf.json_format import MessageToJson from google.rpc import code_pb2, status_pb2 from grpc_health.v1 import health_pb2 @@ -26,10 +28,54 @@ from reboot.nodejs.python import should_print_stacktrace from reboot.settings import EVERY_LOCAL_NETWORK_ADDRESS from reboot.wait_for_tasks import wait_for_tasks -from typing import AsyncIterable, Optional +from typing import AsyncIterable, AsyncIterator, Optional logger = get_logger(__name__) +# How many responses a query may run ahead of what its client has +# reported processing. Bigger means a client that keeps up sees state +# changes sooner, because the server doesn't wait to hear about the +# previous response before sending the next; it also means a client +# that can't keep up is further behind, since it works through what is +# already in flight before it sees current state. One is the most +# conservative choice and behaves like a strict request-per-response +# protocol. +# +# TODO: estimate this per client from observed throughput rather than +# fixing it for everyone. +QUERY_RESPONSE_WINDOW = 10 + + +class _QueryWindow: + """ + A helper class to track whether there is room in a sending window. + + Its main added value is to convert "I've seen response sequence number X" to + "we can send N more responses". + """ + + def __init__(self) -> None: + self._room = asyncio.Semaphore(QUERY_RESPONSE_WINDOW) + # Neither has happened yet, and the first response to be sent + # is sequence number 0, hence -1. + self._last_acquired_sequence_number = -1 + self._last_released_sequence_number = -1 + + async def acquire(self) -> int: + await self._room.acquire() + self._last_acquired_sequence_number += 1 + return self._last_acquired_sequence_number + + def release(self, sequence_number: int) -> None: + # A client can only reasonably send us a sequence number that's been + # issued. + if sequence_number > self._last_acquired_sequence_number: + return + + while sequence_number > self._last_released_sequence_number: + self._room.release() + self._last_released_sequence_number += 1 + class _SuppressInvalidHandshakeFilter(logging.Filter): """Drop spurious `opening handshake failed` logs from non-WebSocket @@ -73,6 +119,11 @@ def __init__( self._state_name_by_state_tag[state_tag] = state_type_name self._middleware_by_state_type[state_type_name] = middleware + # Windows, keyed by query ID, for the queries served over a + # streaming transport; the websocket path keeps its windows on + # the connection instead. + self._query_windows: dict[str, _QueryWindow] = {} + self._stop_websockets_serve = asyncio.Event() def _state_type_name_for_state_ref( @@ -338,31 +389,142 @@ async def _websocket_query( query_task = asyncio.current_task() assert query_task is not None - async def consume_heartbeats(): + # This query's window, if the client asked for one. The + # websocket identifies the query, so unlike the streaming + # transport there is nothing to key on. + window = _QueryWindow() if request.client_continues_query else None + + async def consume_requests() -> None: try: while True: - _ = await websocket.recv() + request_bytes = await websocket.recv() + + # Everything the client sends after its initial + # request either continues the query or is a + # heartbeat; a heartbeat is an empty + # `QueryRequest`, which continues nothing. + continuation = react_pb2.QueryRequest() + continuation.ParseFromString(request_bytes) + + if window is not None and continuation.HasField( + 'continue_query_sequence_number' + ): + window.release( + continuation.continue_query_sequence_number + ) except Exception: # WebSocket closed (or errored); cancel the main query # task to unblock `_query()` and trigger cleanup. query_task.cancel() - heartbeats_task = asyncio.create_task(consume_heartbeats()) + requests_task = asyncio.create_task(consume_requests()) try: - async for response in self._query( + async for response in self._windowed_query( request=request, headers=headers, middleware=middleware, + query_id=str(uuid.uuid4()), + window=window, ): await websocket.send(response.SerializeToString()) finally: - heartbeats_task.cancel() - await asyncio.gather(heartbeats_task, return_exceptions=True) + requests_task.cancel() + await asyncio.gather(requests_task, return_exceptions=True) def add_to_server(self, server: grpc.aio.Server) -> None: react_pb2_grpc.add_ReactServicer_to_server(self, server) + def _middleware_for(self, headers: Headers) -> Middleware: + """Returns the middleware for the state that the given headers + address, after confirming that this server is authoritative for + that state.""" + state_ref = headers.state_ref + + state_type_name = self._state_type_name_for_state_ref(state_ref) + + if state_type_name is None: + log_at_most_once_per( + seconds=60, + log_method=logger.error, + message=_unknown_query_or_mutation_error_message( + is_query=True, + state_type=state_ref.state_type, + ), + ) + raise SystemAborted(UnknownService()) + + middleware = self._middleware_by_state_type[state_type_name] + + try: + assert headers.application_id is not None # Guaranteed by `Headers`. + authoritative_server = middleware.placement_client.server_for_actor( + headers.application_id, + state_ref, + ) + except reboot.aio.placement.UnknownApplicationError: + # It's possible that the user did indeed type an application ID + # that doesn't exist, but it's also quite possible that this + # request reached us before the placement planner had gossipped + # out the information about which applications exist (we see + # this e.g. after `rbt dev`'s chaos monkey restarts). For that + # reason, abort with a retryable error. + raise SystemAborted( + Unavailable(), + message= + f"Application '{headers.application_id}' not found. If you " + "are confident the application exists, this may be because " + "the system is still starting.", + ) from None + + if authoritative_server != middleware.server_id: + # This is NOT the correct server. Fail. + raise SystemAborted( + Unavailable(), + message=f"Server '{middleware.server_id}' is not " + "authoritative for this request; server " + f"'{authoritative_server}' is.", + ) + + return middleware + + async def ContinueQuery( + self, + request: react_pb2.ContinueQueryRequest, + grpc_context: grpc.aio.ServicerContext, + ) -> react_pb2.ContinueQueryResponse: + """Implements the React.ContinueQuery RPC that lets a client + tell us which responses from `Query` it has processed, which + returns that much room to that query's window.""" + try: + # Confirm that we are the server that produced the + # responses. + self._middleware_for(Headers.from_grpc_context(grpc_context)) + except Aborted as aborted: + await grpc_context.abort_with_status( + rpc_status.to_status(aborted.to_status()) + ) + + # Look the window up rather than take it: the `Query` call + # owns it and removes it when it ends. + window = self._query_windows.get(request.query_id) + + if window is None: + # There are several valid reasons why we may not know this + # query: + # 1. The server may have restarted and lost its memory of + # it. The client's `Query` call will have been broken by + # that same restart, and it gets a fresh query once it + # reconnects. + # 2. The query may have ended between the client sending + # this and us receiving it. + # Either way there is no window left to return room to. + return react_pb2.ContinueQueryResponse() + + window.release(request.sequence_number) + + return react_pb2.ContinueQueryResponse() + async def _query( self, *, @@ -390,6 +552,157 @@ async def _query( yield query_response + async def _windowed_query( + self, + *, + request: react_pb2.QueryRequest, + headers: Headers, + middleware: Middleware, + query_id: str, + window: Optional[_QueryWindow], + ) -> AsyncIterator[react_pb2.QueryResponse]: + """ + Produces the responses of `_query()`, but only when there is room in + `window`. While there is no room in `window`, accumulates responses into + a single response. + + The produced responses carry information about the query that produced + them, their sequence number, and how long they were stalled waiting for + `window` to have room. + """ + responses = self._query( + request=request, + headers=headers, + middleware=middleware, + ).__aiter__() + + if window is None: + # A client that reports nothing back has no room to wait + # for; it gets responses as fast as we produce them. + async for response in responses: + yield response + return + + warn_on_flow_control = middleware.warns_on_flow_control(request.method) + + # We'll run two loops concurrently: + # 1. Consume responses from the stream, and merge them into a single + # "next response". + # 2. Wait for there to be room in our window, and send the next + # response. + # + # Under normal conditions (if there's always room in the window), this + # will mostly forward the incoming responses verbatim - the assumption + # being that loop (1) will normally run slower than loop (2). If there's + # no room in the window, or for any other reason sending a response + # becomes very slow, loop (1) outpaces loop (2); in that case it'll + # start merging responses together, ensuring that clients always get the + # latest available result. + next_response: Optional[react_pb2.QueryResponse] = None + have_next_response = asyncio.Event() + responses_accumulated = 0 + failure: Optional[BaseException] = None + + async def accumulate_next_response() -> None: + nonlocal next_response, responses_accumulated, failure + + while True: + try: + response = await anext( + responses + # `responses` is never exhausted, so no default + # is needed. + ) + except CancelledError: + raise + except BaseException as exception: + # Producing a state failed; that needs to be propagated to + # the caller of `Query`. We can't just `raise` it from here, + # because this loop is a background task, so we signal the + # response-sending loop instead. + failure = exception + have_next_response.set() + return + + if next_response is None: + next_response = response + else: + # `MergeFrom` is exactly what one response standing in for two + # means: the newer state replaces the one we hold, an update + # that carries no state of its own leaves that state alone, and + # we keep the idempotency keys of both, since a mutation + # reported once must not be lost because the response reporting + # it was merged away. + next_response.MergeFrom(response) + + responses_accumulated += 1 + + have_next_response.set() + + accumulator: asyncio.Task[None] = asyncio.create_task( + accumulate_next_response() + ) + + try: + while True: + # Wait for there to be some next response to send, or for + # producing one to have failed. + await have_next_response.wait() + + if failure is not None: + raise failure + + # Wait for there to be room in the window. + stall_start = time.monotonic() + sequence_number = await window.acquire() + + # Consume the `next_response`, clearing it so the other loop can + # accumulate a fresh one. It's important to note that this is + # done atomically, without yielding the event loop. + assert next_response is not None + response = next_response + next_response = None + skipped_updates = responses_accumulated - 1 + responses_accumulated = 0 + + # Leave the event set if the accumulator failed while + # we waited for room: its `set()` landed on an event + # that was already set, so clearing here would throw + # away the only notice we get, and the next iteration + # would wait on a task that has already ended. + if failure is None: + have_next_response.clear() + + stall_milliseconds = round( + (time.monotonic() - stall_start) * 1000 + ) + + # Warn every time updates are skipped, until we have + # enough experience with flow control to know which + # skips a developer needs to hear about; a method for + # which skipping is the point has opted out. + if skipped_updates > 0 and warn_on_flow_control: + logger.warning( + f"A client of a reactive query to `{request.method}` " + f"skipped {skipped_updates} updates because it fell " + f"{stall_milliseconds}ms behind. If skipping updates " + "is not what you expect of this reactive read, make " + "that client fast enough to process every response; " + "if it is, set `warn_on_flow_control: false` in the " + f"`reader` options of `{request.method}` to silence " + "this warning." + ) + + # Send the response we'd accumulated. + response.query_id = query_id + response.sequence_number = sequence_number + response.skipped_updates = skipped_updates + response.stall_milliseconds = stall_milliseconds + yield response + + finally: + await wait_for_tasks([accumulator], cancel=True) + async def Query( self, request: react_pb2.QueryRequest, @@ -425,61 +738,31 @@ def done_callback(_) -> None: try: headers = Headers.from_grpc_context(grpc_context) - state_ref = headers.state_ref - - state_type_name = self._state_type_name_for_state_ref(state_ref) + middleware = self._middleware_for(headers) - if state_type_name is None: - log_at_most_once_per( - seconds=60, - log_method=logger.error, - message=_unknown_query_or_mutation_error_message( - is_query=True, - state_type=state_ref.state_type, - ), - ) - raise SystemAborted(UnknownService()) + query_id = str(uuid.uuid4()) + window: Optional[_QueryWindow] = None - middleware = self._middleware_by_state_type[state_type_name] + if request.client_continues_query: + window = _QueryWindow() + self._query_windows[query_id] = window - # Confirm whether this is the right server to be serving this - # request. try: - assert headers.application_id is not None # Guaranteed by `Headers`. - authoritative_server = middleware.placement_client.server_for_actor( - headers.application_id, - state_ref, - ) - except reboot.aio.placement.UnknownApplicationError: - # It's possible that the user did indeed type an application ID - # that doesn't exist, but it's also quite possible that this - # request reached us before the placement planner had gossipped - # out the information about which applications exist (we see - # this e.g. after `rbt dev`'s chaos monkey restarts). For that - # reason, abort with a retryable error. - raise SystemAborted( - Unavailable(), - message= - f"Application '{headers.application_id}' not found. If you " - "are confident the application exists, this may be because " - "the system is still starting.", - ) from None - if authoritative_server != middleware.server_id: - # This is NOT the correct server. Fail. - await grpc_context.abort( - grpc.StatusCode.UNAVAILABLE, - f"Server '{middleware.server_id}' is not " - "authoritative for this request; server " - f"'{authoritative_server}' is.", - ) - raise # Unreachable but necessary for mypy. - - async for response in self._query( - request=request, - headers=headers, - middleware=middleware, - ): - yield response + async for response in self._windowed_query( + request=request, + headers=headers, + middleware=middleware, + query_id=query_id, + window=window, + ): + yield response + finally: + # This `finally` covers the whole loop, so that + # closing this generator while it is suspended in a + # `yield` still takes the window out of a dictionary + # that lives as long as the service. + if window is not None: + del self._query_windows[query_id] except asyncio.CancelledError: # It's pretty normal for a query to be cancelled; it's not useful to # print a stack trace. diff --git a/reboot/templates/reboot.py.j2 b/reboot/templates/reboot.py.j2 index f11446176..61a2128cf 100644 --- a/reboot/templates/reboot.py.j2 +++ b/reboot/templates/reboot.py.j2 @@ -5277,15 +5277,18 @@ class {{ client.proto.state_name }}: __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('{{ client.proto.state_full_name }}'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='{{ method.proto.name }}', request={{ client.proto.state_name }}{{ method.proto.name }}RequestToProto( @@ -5293,10 +5296,15 @@ class {{ client.proto.state_name }}: __request__ {% endif %} ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -5308,13 +5316,18 @@ class {{ client.proto.state_name }}: # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = {{ method.output_type }}() - __response__.ParseFromString(__query_response__.response) - yield {{ client.proto.state_name }}{{ method.proto.name }}ResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = {{ method.output_type }}() + __response__.ParseFromString(__query_response__.response) + yield {{ client.proto.state_name }}{{ method.proto.name }}ResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -5341,6 +5354,13 @@ class {{ client.proto.state_name }}: ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in diff --git a/reboot/templates/reboot_react.ts.j2 b/reboot/templates/reboot_react.ts.j2 index b422f3590..27566aa62 100644 --- a/reboot/templates/reboot_react.ts.j2 +++ b/reboot/templates/reboot_react.ts.j2 @@ -541,7 +541,7 @@ export interface Use{{ client.proto.state_name }}Api { }; use{{ method.proto.name | to_camel }}( partialRequest?: {{ client.proto.state_name }}.Partial{{ method.proto.name }}Request, - options?: { suspense: true } + options?: { suspense: true; warnOnFlowControl?: boolean } ): { response: {{ client.proto.state_name }}.{{ method.proto.name }}Response; isLoading: boolean; @@ -553,7 +553,7 @@ export interface Use{{ client.proto.state_name }}Api { }; use{{ method.proto.name | to_camel }}( partialRequest?: {{ client.proto.state_name }}.Partial{{ method.proto.name }}Request, - options?: { suspense: false } + options?: { suspense?: false; warnOnFlowControl?: boolean } ): { response: {{ client.proto.state_name }}.{{ method.proto.name }}Response | undefined; isLoading: boolean; @@ -769,12 +769,14 @@ class {{ client.proto.state_name | to_camel }}Instance { method: string, serializedRequest: Uint8Array, bearerToken: string | undefined, + warnOnFlowControl: boolean, responseType: protobuf_es.MessageType, reader: reboot_react.Reader ) { const queryRequest = new reboot_api.react_pb.QueryRequest({ method, request: serializedRequest, + clientContinuesQuery: true, ...(bearerToken !== undefined && { bearerToken } || {}), }); @@ -859,6 +861,7 @@ class {{ client.proto.state_name | to_camel }}Instance { endpoint: `${this.url}/__/reboot/rpc/${this.stateRef}`, request: queryRequest, signal: reader.abortController.signal, + warnOnFlowControl, }); for await (const queryResponse of queryResponses) { @@ -909,21 +912,44 @@ class {{ client.proto.state_name | to_camel }}Instance { // orphans list with a length greater than 0. In this case, we don't // want to skip checking the expecteds list just because we have // already checked the orphans list. - if ( - expecteds.length > 0 && - queryResponse.idempotencyKeys.includes( - expecteds[0].idempotencyKey - ) - ) { - await expecteds[0].observed(() => { + // + // A single query response can report the idempotency keys of + // several mutations at once, because the backend aggregates the + // keys of every state it skipped over on its way to the state this + // response reflects. Two mutations may also share an idempotency + // key. So observe _every_ mutation whose key this response + // reports, not just the oldest one. + // Both of these are looked up by set rather than scanned: + // a response reports the keys of every state the backend + // skipped, so the further behind a client falls the longer + // both of these lists get. + const reportedKeys = new Set(queryResponse.idempotencyKeys); + const observeds = expecteds.filter( + expected => reportedKeys.has(expected.idempotencyKey) + ); + if (observeds.length > 0) { + const observedSet = new Set(observeds); + expecteds = expecteds.filter( + expected => !observedSet.has(expected) + ); + // The one response we have in hand is the response for + // every one of these mutations, so publish it once, on + // the last of them, rather than handing every listener + // and the offline cache the same response N times. This + // is the same shape as the `orphans` loop above, and it + // matters more now that a response can report the keys + // of every state the backend skipped. + for (let i = 0; i < observeds.length - 1; i++) { + observeds[i].observed(() => {}); + } + await observeds[observeds.length - 1].observed(() => { if (response !== undefined) { reader.setResponse(response); } - expecteds.shift(); }); } // If we don't have any orphans to observe and we don't have any expecteds to observe, - // or at least, the first expecteds _is not observed_ by this response, then go ahead and + // or at least, none of the expecteds _is observed_ by this response, then go ahead and // pass on the response because it might contain new data that should get shown to the // user (e.g., in a chat room this could be a new message from a different user). else if (response !== undefined && !haveOrphans) { @@ -1146,6 +1172,7 @@ class {{ client.proto.state_name | to_camel }}Instance { requestBearerTokenHash: string, serializedRequest: Uint8Array, bearerToken: string | undefined, + warnOnFlowControl: boolean, offlineCacheEnabled: boolean, cacheKey: string | null ) { @@ -1254,6 +1281,7 @@ class {{ client.proto.state_name | to_camel }}Instance { "{{ method.proto.name }}", serializedRequest, bearerToken, + warnOnFlowControl, {{ method.output_type }}, reader ); @@ -1292,6 +1320,7 @@ class {{ client.proto.state_name | to_camel }}Instance { requestBearerTokenHash: string, serializedRequest: Uint8Array, bearerToken: string | undefined, + warnOnFlowControl: boolean, offlineCacheEnabled: boolean, cacheKey: string | null, setResponse: (response: {{ method.output_type }}) => void, @@ -1306,6 +1335,7 @@ class {{ client.proto.state_name | to_camel }}Instance { requestBearerTokenHash, serializedRequest, bearerToken, + warnOnFlowControl, offlineCacheEnabled, cacheKey ); @@ -1610,7 +1640,7 @@ export const use{{ client.proto.state_name | to_camel }} = ( function use{{ method.proto.name | to_camel }}( partialRequest: {{ client.proto.state_name }}.Partial{{ method.proto.name}}Request = {}, - options: { suspense: boolean } = { suspense: false } + options: { suspense?: boolean; warnOnFlowControl?: boolean } = {} ) { const newRequest = {{ client.proto.state_name }}{{ method.proto.name }}RequestToProtobuf(partialRequest); @@ -1671,10 +1701,16 @@ export const use{{ client.proto.state_name | to_camel }} = ( // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = options.warnOnFlowControl ?? true; + const reader = instance.start{{ method.proto.name | to_camel }}( requestBearerTokenHash, serializedRequest, bearerToken, + warnOnFlowControl, offlineCacheEnabled, cacheKey ); @@ -1708,6 +1744,7 @@ export const use{{ client.proto.state_name | to_camel }} = ( requestBearerTokenHash, serializedRequest, bearerToken, + warnOnFlowControl, offlineCacheEnabled, cacheKey, (response: {{ method.output_type }}) => { diff --git a/reboot/templates/reboot_web.ts.j2 b/reboot/templates/reboot_web.ts.j2 index ee651f664..3f840b11a 100644 --- a/reboot/templates/reboot_web.ts.j2 +++ b/reboot/templates/reboot_web.ts.j2 @@ -433,7 +433,7 @@ class _Reactively { async {{ method.proto.name | to_lower_camel }}( context: reboot_web.WebContext, partialRequest?: {{ client.proto.state_name }}.Partial{{ method.proto.name }}Request, - options?: { signal?: AbortSignal }, + options?: { signal?: AbortSignal; warnOnFlowControl?: boolean }, ): Promise<[ AsyncGenerator<{{ client.proto.state_name }}.{{ method.proto.name }}Response, void, unknown>, (newRequest: {{ client.proto.state_name }}.Partial{{ method.proto.name }}Request) => void @@ -452,6 +452,7 @@ class _Reactively { signal: options?.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options?.warnOnFlowControl, } ); diff --git a/reboot/web/index.ts b/reboot/web/index.ts index 680b135b5..b92e60383 100644 --- a/reboot/web/index.ts +++ b/reboot/web/index.ts @@ -294,6 +294,7 @@ export function reactively< signal, bearerToken, websockets = false, + warnOnFlowControl = true, }: { url: string; state: string; @@ -305,6 +306,9 @@ export function reactively< signal?: AbortSignal; bearerToken?: () => Promise; websockets: boolean; + // Whether to warn in the console when this reader falls behind and + // the backend skips updates for it; see `logStall`. + warnOnFlowControl?: boolean; }): [ AsyncGenerator, (newRequest: PartialMessage) => void @@ -381,6 +385,7 @@ export function reactively< const queryRequest = new react_pb.QueryRequest({ method, request: request.toBinary(), + clientContinuesQuery: true, ...((bearerToken !== undefined && { bearerToken: await bearerToken(), }) || @@ -394,6 +399,7 @@ export function reactively< request: queryRequest, signal: responsesAbortController.signal, websockets, + warnOnFlowControl, }); for await (const queryResponse of queryResponses) { @@ -418,26 +424,118 @@ export function reactively< return [responses(), setRequest]; } +// Tells the developer that this client fell behind its backend, which +// merged updates it would otherwise have sent. The state we go on to +// render is still the latest one; what was lost is the updates on the +// way there. Warns every time that happens, until we have enough +// experience with flow control to know which skips a developer needs +// to hear about; a reader for which skipping is the point is created +// with `warnOnFlowControl: false`. +function logStall( + method: string, + warnOnFlowControl: boolean, + response: react_pb.QueryResponse +) { + if (warnOnFlowControl && response.skippedUpdates > 0) { + console.warn( + `[Reboot] A reactive query to \`${method}\` skipped ` + + `${response.skippedUpdates} updates because this client fell ` + + `${response.stallMilliseconds}ms behind. If skipping updates is ` + + `not what you expect of this reactive read, make this client ` + + `fast enough to process every response; if it is, pass ` + + `\`{ warnOnFlowControl: false }\` in the options of the reader ` + + `to silence this warning.` + ); + } +} + +// Tells the backend which responses of a query we have fully +// processed, which returns that much room to the query's window. +// Retries until the backend confirms, since a lost request would +// leave the `Query` stream with less room than it should have, and +// eventually with none. +async function continueQuery({ + endpoint, + headers, + queryId, + sequenceNumber, + signal, +}: { + endpoint: string; + headers: Headers; + queryId: string; + sequenceNumber: bigint; + signal?: AbortSignal; +}): Promise { + const url = new URL(`${endpoint}/rbt.v1alpha1.React/ContinueQuery`); + + const backoff = new Backoff(); + + while (true) { + try { + // Pass the options separately rather than pre-building a + // `Request`: `guardedFetch` reads `signal` off them to tell a + // deliberate cancellation apart from a server it cannot reach. + const response = await guardedFetch(url.toString(), { + method: "POST", + headers, + body: JSON.stringify({ + queryId, + sequenceNumber: sequenceNumber.toString(), + }), + signal, + }); + // A `fetch()` only throws on network errors; an HTTP error + // response resolves successfully, so we have to check for it + // ourselves. + if (!response.ok) { + throw new Error( + `Continuing query '${queryId}' past response ` + + `${sequenceNumber} failed with HTTP status ${response.status}` + ); + } + return; + } catch (e) { + if (signal?.aborted) { + throw e; + } + console.warn( + `[Reboot] Failed to continue query '${queryId}' past response ` + + `${sequenceNumber}, retrying after backoff ...` + ); + await backoff.wait(); + } + } +} + export async function* reactiveReader({ endpoint, request, signal, websockets = false, + warnOnFlowControl = true, }: { endpoint: string; request: react_pb.QueryRequest; signal: AbortSignal; websockets: boolean; + // Whether to warn in the console when this reader falls behind and + // the backend skips updates for it; see `logStall`. + warnOnFlowControl?: boolean; }): AsyncGenerator { const url = new URL(`${endpoint}/rbt.v1alpha1.React/Query`); - if (url.protocol === "https:" && !websockets) { - const headers = new Headers(); - if (request.bearerToken !== undefined) { - headers.set("Authorization", `Bearer ${request.bearerToken}`); - } + const headers = new Headers(); + + if (request.bearerToken !== undefined) { + headers.set("Authorization", `Bearer ${request.bearerToken}`); + } - yield* grpcServerStream({ + if (url.protocol === "https:" && !websockets) { + const continueHeaders = new Headers(headers); + continueHeaders.set("Content-Type", "application/json"); + + const responses = grpcServerStream({ endpoint: url.toString(), method: "POST", headers, @@ -445,6 +543,54 @@ export async function* reactiveReader({ responseType: react_pb.QueryResponse, signal, }); + + // The one `ContinueQuery` that may be in flight at a time, and + // whether it has settled; see below. + let continuation: Promise | undefined = undefined; + let settled = true; + + for await (const response of responses) { + logStall(request.method, warnOnFlowControl, response); + + yield response; + + // Only now that our consumer has processed the response do we + // continue past it, so that we can't fall behind a backend that + // produces responses faster than we consume them. + if (response.queryId === undefined) { + // An older backend doesn't send a query ID and doesn't expect + // to be told. + continue; + } + + // At most one `ContinueQuery` is in flight. While one is on its + // way we keep consuming, so the one we send next names only the + // newest response we have processed; the backend credits us for + // every response up to that one. + if (continuation !== undefined && settled) { + // Throws if continuing failed, which reconnects the query. + await continuation; + continuation = undefined; + } + + if (continuation === undefined) { + settled = false; + continuation = continueQuery({ + endpoint, + headers: continueHeaders, + queryId: response.queryId, + sequenceNumber: response.sequenceNumber, + signal, + }).finally(() => { + settled = true; + }); + + // A failure surfaces on the `await` above, but a read that + // ends before we get there leaves it unobserved; observe it + // here too so that it can't become an unhandled rejection. + continuation.catch(() => {}); + } + } } else { // TODO: while technically we could `await // grpcWebsocketServerStream(...)` doing so will leak websockets @@ -458,12 +604,26 @@ export async function* reactiveReader({ heartbeatRequest: new react_pb.QueryRequest(), responseType: react_pb.QueryResponse, signal, + // Continuations go back over the same websocket, so that a + // reactive read costs no extra round trips; since sending one + // costs nothing extra we continue past every response as soon + // as we have processed it, rather than past the newest of + // several. + continueRequest: (response: react_pb.QueryResponse) => + response.queryId !== undefined + ? new react_pb.QueryRequest({ + continueQuerySequenceNumber: response.sequenceNumber, + }) + : undefined, }); for await (const response of responses) { if (response.responseOrStatus.case == "status") { responses.return(); throw Status.fromJsonString(response.responseOrStatus.value); } + + logStall(request.method, warnOnFlowControl, response); + yield response; } } @@ -755,12 +915,16 @@ export async function* grpcWebsocketServerStream< heartbeatRequest, responseType, signal, + continueRequest, }: { url: URL; request: RequestType; heartbeatRequest: RequestType; responseType: MessageType; signal: AbortSignal; + // Produces the request, if any, to send back once the consumer has + // processed a response. + continueRequest?: (response: ResponseType) => RequestType | undefined; }): AsyncGenerator { url.protocol = url.protocol === "https:" ? "wss:" : "ws:"; @@ -848,7 +1012,17 @@ export async function* grpcWebsocketServerStream< // suspended at `yield`; the loop re-checks after each one). let data: ArrayBuffer | undefined = undefined; while ((data = messages.shift()) !== undefined) { - yield responseType.fromBinary(new Uint8Array(data)); + const response = responseType.fromBinary(new Uint8Array(data)); + + yield response; + + const continuation = continueRequest?.(response); + if ( + continuation !== undefined && + websocket.readyState === WebSocket.OPEN + ) { + websocket.send(continuation.toBinary()); + } } if (error !== undefined) { diff --git a/tests/reboot/echo_rbt.golden.py b/tests/reboot/echo_rbt.golden.py index ee0d4e1df..ce65a984e 100755 --- a/tests/reboot/echo_rbt.golden.py +++ b/tests/reboot/echo_rbt.golden.py @@ -20838,24 +20838,32 @@ async def Replay( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Echo'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Replay', request=EchoReplayRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -20867,13 +20875,18 @@ async def Replay( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = tests.reboot.echo_pb2.ReplayResponse() - __response__.ParseFromString(__query_response__.response) - yield EchoReplayResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = tests.reboot.echo_pb2.ReplayResponse() + __response__.ParseFromString(__query_response__.response) + yield EchoReplayResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -20900,6 +20913,13 @@ async def Replay( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -21015,24 +21035,32 @@ async def WaitFor( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Echo'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='WaitFor', request=EchoWaitForRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -21044,13 +21072,18 @@ async def WaitFor( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = tests.reboot.echo_pb2.WaitForResponse() - __response__.ParseFromString(__query_response__.response) - yield EchoWaitForResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = tests.reboot.echo_pb2.WaitForResponse() + __response__.ParseFromString(__query_response__.response) + yield EchoWaitForResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -21077,6 +21110,13 @@ async def WaitFor( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in diff --git a/tests/reboot/greeter.proto b/tests/reboot/greeter.proto index bc9968892..84833c1f3 100644 --- a/tests/reboot/greeter.proto +++ b/tests/reboot/greeter.proto @@ -113,8 +113,11 @@ service GreeterMethods { }; } + // Reading this reactively never warns about skipped updates, so + // that tests can read through a method that opted out of that. rpc Greet(GreetRequest) returns (GreetResponse) { option (rbt.v1alpha1.method).reader = { + warn_on_flow_control: false, }; } diff --git a/tests/reboot/greeter_rbt.golden.js b/tests/reboot/greeter_rbt.golden.js index 0a064c8d2..cdec13c55 100755 --- a/tests/reboot/greeter_rbt.golden.js +++ b/tests/reboot/greeter_rbt.golden.js @@ -5507,8 +5507,8 @@ Greeter._ConstructIdempotently = (_j = class { _idempotency_1 = new WeakMap(), _j); export function importPys() { - reboot_native.importPy("tests.reboot.greeter_pb2", "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"); + reboot_native.importPy("tests.reboot.greeter_pb2", "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"); reboot_native.importPy("tests.reboot.greeter_pb2_grpc", "H4sIAAAAAAAC/+1dW3OjOBp951doeh7s1HrIbO/MPnRtttaVkGy2knTK8Wz2jcIgO2xj5JHEpL1d/d9XF7ABC/BFuOlYeUj5Ih3BkY4QRx+ffwQ3MIbYozAAkyWgLxDMRo+X4HFJX1AMFhhR5KMI+Gi+CCOIwSJKZmFsg6uP4OHjGDhXt+MfrHfv3l1GIYwp8OIAEIj/YCX9yCMEElYVY0gWKA7CeAYokqCTZPpTAKdhDGWF0IfEZjhWOF8gTMEML/zs9auHY1aXWNYUozmYITSLoJ3BgLQUnC/o0l1M3gOPpGXcAFE3KyfeyEK8lMSikFBiYzhBiIJV0xBSiDMoUURUlsXEy6yMQLJuGGXujfPgjIZj58r9tzN6uv34AC5A78/2X3+x/9KTJdaf87OzXZfRREIUu67l/OfRueR1ndHo48gdOXfO8MlJEX61f+5ZT5f/dK5+u2NF0i/dK9YYL/GvJIbg/a8D8P7n97/0rBVqzI6TJAt+TozkC3DtRQRaFsXLDxZgf5JMcSQJDaOQhqy3Ug6mISZ0hRQSN0KvEItqlfjqOv38qQ+AmqozC3724YKCW9G8gzHCH+pbG+OEnUw4rSgha2cjx+Yv+uIjcea9MR/o7NTBwvM/eTMIwphQL4oYdEiAR0EKCr7kD//roLfC+BNDAZOESs2sROSjgIPJUXMuR8x5bkS5gvDFEgRwAeOAABSXMHmBEP394ouaqq92qfxjBD0CQbKYYY+1vUQJlqc2R0ESQa64JsgSIsIgQK9xHq94fgnhUpaoP1GEIvK3iyJR5YMcvzBa094Ar2EUgQlkcwpkEwaAvLc5Z1/UKthgnfgvkJ9aAKasIoaSAN5ZapGwoxmsEEZJTMM5fJbHIj4+syxLzFbgRnbUPWSzX0CeaDLpo8l/oU/P5HhiE9R9SMTZs+LIDwUnAfKTOZv9PMpHDDst/oafkJyjmDDYdMXnNoHBZj3gumEcUtftExhNB8B/8eIYRmkjaUOXiA1JnPgUYdtafTHEM7Iuxv/Syh/AUIr5Ur6381ir17w9+xJDdtxMQ2lVO4k9vHTF/34Bm//1zvOTpF2k6Fxi5fjN/jD8PWH1XDa5h14U/g/ii8aZND2ykaxqP2VVx+iJYka6qhV+ZSFspod7NSRr29dsKqxqgmHMQsJqwsCdi7O+4HPPWZFTQYseSsVbXYwKsCMQmrajjc8nSIcBV174h6aRmkfUxW4e8wgkF5vTxvUYezHxfD576ae9Atz0QLEHlmO0mvDZCwo/U138K6C3Y795EW07/OX+hG/dgm6Knc+sfOxFLVJdauIUKWcnd4fiGVty8bXWNaT+iyamFci6ZhQV9sEzy7dj/RmHrEYrtEvoExzYN5A+v6AIPlFt6+gCpLbFXx70WItAiDUwfO2F0XNIXxxhC/DbKi0sb8Ce4ODNOBhOMitFI7Ep6AnS+ozwp2mEXvXwmaF1hchm7WdHrHFVfOXFM4hRQq5DGAVED7MlUF1TbQn2e1owPFGE2dXBTzBhdzX3kBBuiOq551ZBa7v1U4Ef4x5Q3a62YT+CXtBOd6iQdfWGCvsInaFuVltfrO7mhnHQok4am9FmsDY1dAzvtfkYDum/Ci9f7jHidvx8aSenbn7aMQNWU9z5F239Q9pbWf4S2CaQunxDpi+Mf77KT8gle2//9nB7/3jn3DsPY+fqTFkvgJSt2Ui/JwkCsdwAjSBvHAY/9NbVsBcSCB4QvV1/L7bo6iqvuBH9YKhRUZN3Ew1DKoYq3GNDlposhdVrqGqmqmTVGsqUlCl8UcPUFkxJm9RQpVwc5B1KQ5GKog3P0tBUR1PqQBqSVCRlJp1hR8VOycMzJCnvWVR37IYqFVUqb8owpWKq0RIytOVpszhnXhC4ao/LpciVQfj9NLQeD9Ko/JQwdk6paea+eHEQQcx3V74UTLZeGtr5QYaV5txNd7P6puEpLVTZehpuOVAWynzMPSM4pV1Z5xQWvMpDokQbPNGz4tuejOPUQZ9A0speISy0HfKKEaE7clcIFdRBYR5QK5OqAMR2CFXGHu7Ia1U0pg6KK7BPmm1V7KUerhXIOzCtZXu5ilxd4Qj1dJbjK/XTWmrhzdOrCqrUwqoCWOusUBey2WGG0/jJFiiWyG99wBZjJrUstPKIehdcqlDMFhdeYsmzE5ubsZE6GN1AfeuDshwJqZPEFPOtU7gKftTBXQbWFdL2iKTckb5yhKMOFkuYWqfGitDJLo1IdUyWlvtSFbLeW6a6MK+W7p1qo7p25F4ZtKiDehWwVubrQiLbIb42GnJH3ptjErU4g02t6DUNtw1/bMlP3Drycbu++ir+i+QMoZ8RnqUXKfm7bqlYsV96NdGpvYHKL5YetnSVbe5FZ/i8bFao3y+1OjjbqLcRx7muvc9RWRb4UaabkGGg7MXCwxSgKc81wTNMjG65eT+8A8PHW1sZLKo/SPQfhBf05dGWw0azXY1Cj1APz8qmLxIraHLRL2k1jUB2fUYiOwo2csjFA4pL2vG9qKlIyMYeG5HwQuSKKVVH8wUb9jwriqLmqxdSd4ow604vWCoK8KQbKKGKbxgpXuBRT3yV29HBkCY4loMZfl6wYST4rgm03prIPXJaaE5eoS1FRTomGgeEuqPrR0jlAKjre2W3q3u8+Gl1RHe1gmRwsRFQtwSkymCiN1WJroQkp62eQki1EVG3RFSTLaWVtCiak5+ctrKqnlswIuuWyLbLTmT01n29qR59MWrrmtqac1HpsnAPNvGNoKofkDLC6rKw6jOPGYF1Q2Cqx+mMrjqmq+Y8c60mlDMa06mx9EFMI7JOi0yZVdBctLphtxce1zVC6pjtXpNDsp1kkYenhDxtPW0+22001S1NNWUMNRemTgkpe/rfyKibMlLnhzUi6oSIVtkhjHq6pZ6KbMC6ZKMxue9pC6icQMToqFs6qs/93FaSZ3NVOixISZkPxEirY9FKW2Qtbjeld1uJu09bfcocRkZ83RLfFnndW03g3lKa9tNWXnNOLCPDjj03smMW/+Ol6z9GUv5TUGv6tNhlhPxPb/bXgROM2RGOGV97/riFoOc8h/P9/IoRP1otP6nDRuC8jkkiSmxJ5QbcCRKKFq9e8fcjJYU7jckVjMbfIJKAx/ndoawtfT+zLDisYXePcWpILl8p2v3tmfW0YLKkqjMWl2ZPQ1NFYmc58ov0uDway2PLDMNTfjgZtrZMUVyYAXVlJs6thLQkIVnjfT9posTKauc8RuWFZIG+9Jq/RxKjEuxbZzFb4KTs5Veie6WAknC60z4VF02tpXoqrZf2GpJVlB42Ik+S2baSAomJvCu5gGoPZr8UQALyaJl/cqtRY+N+Yxu3ya86XpxNrVty6mEA5bs4o5t9dKMydA4TTpM7aeTTjSia9H51407V6Gc7/VT7zbtTupM7rd8h1emDmstS3g0y6jpMXTWXp8PlVbc7YUTWlc11FCF8z1mB+K3usYvTEye67xZ7jqTzNZquHbc14hG23PKNadlzyw+gVrfe1kdutpTU5r+iKzTtAeQGvY4tgDWcVq9wU0jtmIUKDX1jtzDX850xDbc4pj29wxzysSzE3ORjnJBv7SBudTlu4bqr9ep6AovM/wNf+HyF8KYAAA=="); - reboot_native.importPy("tests.reboot.greeter_rbt", "H4sIAAAAAAAC/+y9a3fbSJIt+l2/Ai1/EFkjs7rO656rXjz3eGxXX6+p15Jd7XWPx4uCSFBCmSI4BGmVuqb++43IB5AAMoEEHxIobq/ukkQiE/mIiNwRGbnzRfAQLqYXwSROw+tZdPIiiNNkuboI0i/xYjSNxUfL9ZQemSf/EdIfdw+Lh+z5l9FymSxfjpNJNDydrufjl8totV7O05dfw9k6Oj2hfy+CDwkVXgU30Txahqso4MeD+9toGQXx3YJeF02CeXgXpcFdfHPLD66C9DacJPf0BT03D8JgnUZLqipdRON4GtOjaXIXiVJBPA9Wt1G8DBbLZJUE3OiAfl5H/HGQ8iNhGiTzKEimQbJeZi+l+sRrz4PeNFkG0e/h3WIWXdDbltF/rKN0RXVFM9m2SXC1XseTq35wHwXX8XwShLOZqiml1+m66J3hKgipa1TldTyZUOupgWeibWdBSAVX3HP6lgYinAfz6Gu0pCGZzeJJNODher+ip8LlRNc+OJkuk7tgNJquaWyj0Uh9QZXRsIarOJmn3MN3P/7y8+UH/ZTxpZiDW27RbJbcx/Ob4Mdf338IwsUiCpc0TqItPFZL7jMNEv+uXn4epPF8zF8nafYhi0H4wCMcz2mi40nQu14mX6J5P4hlaT3XEznZMU9teheuxrc8pfHqVr5jnq5oGMVMzOLrZbikmR2cqO4to+skWQ1oeFLqBTc776T8bpR/d+L6YkCvHH8ZZQ0acYPoP3cLGhwS4d7pd4P/PvjraZ9H6dWHD29/+vDu559Y3IPVw4ImVIgXdUDIVXqbrEkirg3J1b0hAVzP/2NNw0FSwz0y/gk57UWDm0FwJSaTquYOqZ6+mj9c9Qc0RyQ69+IF45AEPhjPwvQ2Sot1ifexOrycRNN4Ti24i2h2Jkr0bsOvhuDziwfBr2lUrGO6ns0eXmaNVaKrGqhGUjZxINomZioKJ9nchOnDfBwnxoyoT/QD1+t4tooLgqk/0o+Mk/kq+n31NVyaTxmf6gcn4SrkoUgj80HjU/3gTZLczKKB0LXr9XQwidLxMl6sSLnzcvKhkX5olD/kqua3NJmPSEnuWLOd9RhPuSqiQU7Dm6imEvVEVsFyMTafpj/Nr0akPqt1OpCDb6pH9p38SloQo4iWPOMTa2lRWD3LHTSe4j/1V4lZPMnmY7UMx9F1OP5ifJt9ph9is2p8z3/qrxbx+MvMHC75QdFAVKyC/nqW3Azo/8b39Bf/nxTghVDuiyC+mZPx+yRLfM7aLbXTaLT4oGSYwjgZcEeS6bRqmejLkfpSF+P1cZUks6KxVp/JGQqvx5lxv055qFZSuU1Fux6Pil/KsqQP0Sq+05Yp/7ugMuKj7Bd7Sf59Es1Woa1o9qW77D95rXUU5e+UNBaVw6yAhO9uMVpc/5caTSk8V1vj/ZJXumXaUKH5mLW+QXS3WD2IWlTNb/mDmiqzAiPxpEV+eBatKxvLj/qy0Bg2CKoapaLWXhkqnHVn9c9ZMg41aGGUNRIflKZLPTYqfG9p+pgBkLXd/I2jQLQcFbS9VEp8bSsqF4XUUVJ9ayl4S4tWtHSUU19aihEUo89W0Xz8YC9qPGArTu1ZzsNZSuCDcFg0G92FczLrS0dl+vFR6fHaqu8IXM6ie4aaDbXmT9ZWuArTL9SEkABTU43Gox5VkrOwENBv6Vdv/ryl8sWM1o+7aL6y15V9bSlKmOlrPHaKQ/a1rSjpUqSnxVW+8Iy1kvW1syx9ZbMPPCAO68Bf2YoI1Govwl9ZipDyiAmwl9LfWgreJ8svU/IpHO/LvrYUDdcEY62l+BtHAfGfZBn/0zkJ/MDIeMpV0YrdFXYTGADXVlZ60lbhtfQE7HXIL0vF0mhFUPjG8l79TanAnLyW39LB4oF6Nq+Wkl+P5NfS3KuC5uL8hgT0A/39kVwI/vl/ipZf1SXWatujWZOuySv7LpwtbsPvzOLX5Hepj22PDnQjCwuWWWqUP+GC0OH8oWEdV0/oCtIHc5DpL/3F3XghLEK0HEzDdEV/Gs/RXyP55Uh9WZoPLq3WneoIcmn1paXYOraXWMfCBZ1MYvbaaTV8oFIvo98lHKTFVjkHqYgiRPP1HTmlYmEng81jcpdM1jRWarUndJQO1GtvllFESmxil94JO4Kvk1myPFe/ko+3XI9Xr+aT9+QNRZfReE1e9NfoR/neSxkU8X46XdAzkXp8GZFAFWtQH5mPvQnnZDuTdfo9B17SwvNvOdTE4vgPDi3Jz/4erT7eJrPo/apc+9+5x7ZPzNf9yKuMGILCk+bH5uOXhBdqB8X+QLGK4rfy0/fR6tXkt2i8oi8KFRa/MCuiMV/cczuLz+eflh5umE6PKfxAD/+QzG8u13OOq3wflV/OZkL+9lHZ/bwCEV35lTQq0EEL8smX0TRaEoSKjFBXUe3DRTwwAlkWw8BP3K5WCw+b0RwlqHsqw/KuB4oOic3+JYtKLwrfS/TT+G0hDOBS86bvZSUn5A0zLB2WPOSBBP/8XW804ujQaCSm8GMU3Cfzs1Ugwn4czP3lYRLOV/FYuCMR26CIPNz7WxGFvY0eRCx0PZ+IIKeyGTQKgxPxfDq6jkiYRtlX0eQioCXwE/31mZpFv/boxSLOE/xKorS6EBK2oL9PTn796f3bD/SU+IKfOzkh8ZKaHi0/JL/w3PTEiy70pwNhK86DbL1QX7sGaqDK9c0XG2/5noytfI/43rM2qSdxStiXrD15W6ocPT+jDn1PYJi1Jnj5v4rtlo2QQXb5LrMtRZOq+6+KyA/zcSg+LN/lbHbx4UIrdM0n7paUxihvi+f7igOxaVuEqSoNivisOibiY88hkVUUWyHLOxtRGQ/VDL932Udjw2a8my/WK7naysas4hXvgRSDwD8vJCSRavmfUuGkDLNxaPF4qJczzzJK7TjMS9bM2mneXeD9pZ8Yokq9mooP4lRsMNAC0xO9OpeV9uUuDH9iFhWfloqd6IC5LJ/9SW2Uf6jmiVEP4zQKPpCLJZBKXlYE3E9f815PssqNYGaBNK4TOy9UPDgtFT3zk4uzC7VfdSZae6Y7V66OXsOiES9p3RXvO6MGneVP9R1jyDNdGEK5++Y5gqL0oQwgN3bn45eJfmEQs0+9RzKv51CGM2vxFmMqNXs0Cpc36WjEO9BjgRLOg8p+FQOHP/70MgX5cOmaPynt4UrEbx7aYKtFiBBXwr/4SoStonzwuLbsrxPT1FvtYj7j33yjq1NSUlgTCo5RA2goPNuwQBaebV6mC4+3RwyWllkb7d0QD7hgPuk3GH6rtPlwa6xQbZStua3bUAEKLRf+u2gV8pats0iu0Fy4EQKY7fNBAM9x9TLHYM+Ll56+whDqD72HMasl+4RnvcNjqRvcYjyLcryfNWwXi095Rm31ZN3nuvQf1pXHHD7fhccW3WpYf2xFGiyvrUjzImAr1X5Rcje3rkNtW+exUlkKtBo2vzXDUqb18uVsaU1XNm1YZU1r652KMsvreLUMlw86ecdZtk2fBz/Rf6KJisSWXrnknMHVKJxyBd+N0ogs4cT5Wo4pNS6nlib4rKpH4NNYRma3no1jZMtiVRzh8rf+I12pNw9ybCyfBzBR5W63mLDNx8Vjnq26XJhr6xPe822vP/uajUP3Z8/aiRYzyL3cDxLbyoVvqfnWqityLV5R/nQT4bO9zj4R/ErrN1aoaJlpX8T4YRnO01BsIG0AHhtK7wVHNrxzH5Cy4ZVbtNkDaNaX3QPmrH/h7uFn/ft20FyAUs+xBj4FPgU+BT4FPgU+3SU+rV91/KHqw4cky5J8LbNBvYFqTVkJR5zpaQNx1MQH5NW8wwlLG15bhko1r9i4hV4g1F1yk+GzwTj3G1yYcxdj5wsy61tXgJgu6OWuogi8NjBVdq1zv3AznXurzi1so3uOOvaig4537UMXHa/ausWtddNewz501P6mPeiq/UU7a21r3bVX9Qg6bH+xty5b0839VLim6K40t+YVO1LYmjds2j4f9XQXbAje1JRsFn532dYRnMYeeHR12wZXYjjpLIoW8mSVRJ6pMzISz1fNgRH3632iItXWFBy66tfe3pyl5uw76lgnPLmawcs9umpHWrhz1NP9eHPuibM5Q5Y+iDMVlY/txtw9TBva8I/LmD7czIgXy+7HihffsRczXnzFxi1sb8gLJXeEr2resBtcVfOCrVvng6NqqtgPfqp5oXc2b/FIpF9Wr62MT0JrtPRIp7VVvmF+b7QsZbTa6m7dJJ9MX0uJpgGyFGnOurUUap8B7GxsXXc2bpuHJtmK7kWDbC/y1Zzvw3jG54vf/j6OBBjz1B5nuR2tUs76d7NCOavfqGUeuuQqtZtVyVX7TlYkV+VbtcpDf1zF96JDrpe11aNXkvmipRaVSu1Yh0q171aDSpVv0KoW2lMss1vdKda9U80pVr1Fi1poTbHwXnWm+CpfjSnzJTSoSvnxBiBSfrxZLssl2qM1exNdHWjTIg8VKT28G90oVboTpSjVuUkbPNSgVGov8l96h6/gV/hevOTfUWpHS4Wj9t0sFY7KN2iVhx7YyzRYC3uhRtG0F2vtutQ1ub5bW7SwEq1tPKtYjNEWutaihJYg7yJpNJu2eFxRULUocR2FS5oJQXnWqis8kS0KMMlrm36v1tctHjfIGVukTEr6vpp2+RBT2IXMJya/rwOWXYm620dmq5OW5TC7K4dIclQVU9Yq89KQpGbwXB3SqKqG72FQFbNXcVTlhy2G1SQYO6xxlS3f+cCyiS9uxtEH/ttvXPrgBpNbvfOBVItfYSw1YaPvcOo6Dm5EVcN3PqgmPiiMrPmF9/AWaju4MTZbvwf7yu0pWVfBdu9vW0UNB2hZucjOB5QRZ2E4xbUDvoMpSh/cUHKrd79AERYvLlD0gf8CxaUPb4GiVu98IA0vpTCeJve877CadXXugFLT6BqN3/kpJe3UlSRWfthCalUtBze2uuVdIF7bnHDGy7GzHweR4yEPgMiYkJ9DY69NgX5ZnYrSNeN4a24WY17JcDub+kFYWzUa6HFNmnHcH7rZaizAGq7W/MALrdiHTqzqcuDEJT3Ny7StHrGkcS3imqDmFco69GzNxdDTL/7G2VaVabq4RvNaED+DZG+gUlrZSPmHNexuV39v/qU60u8mIqa6sk3HvOvKepAf1RXf4EB9c0+8Or1xw33om2pKbjbYnrxJNYXbH61v7IRPd7dusyXav+EJ+fJLmkmWaprmFyOunrRue77a/1S1/a6Cpz6GWzOEZjB5Z2eoy+/aFzZqPElrnp/Vp2at9Co1I+S7MtRdZNGwMNQVbTBVdUWbrWtd6farQnM3fDq8aas9loSaghsNs59xrSnbej1o7IFHV7dtsEf6RE0Ne0mlqHmfr/p6X87TdEWEbz1NVyX41uNxmYNvVRvcOdGut60HaSed87nEwrOW7SfN884Jz4ra34rRqqNth2en/aqAzkm0WN1udQbQ9/U+wFK0pgArxSfeoFKW71xc13eIcuAoOtKFk36FGbHBQdlSrkT8Zr8OwLP/tevKyYuaf8EP0U04fghuLn95HbzP7tesKyIuo6cBTiNBscJjvYxm0ddwvgp6yXz20A+myTLIL+sU15rHd4uZuvYzmOXvpMrUg3xPexhcyk0yFQobBO+E+MfL7A2rJBjPYqonHUhl/jH8EslO/H25GKsuhHwxvBiAF8Er831Zs+T8j0O+C+uar71aRkG6iMbxNB5zi+fBFT9xda5quY7kle62utKgF6ZBdkN9cP0grvQTz1wJNRhfqWoWs/VNPO8Hk0QITHorrn+dP1CP7+5oMK9DdW18GiQrvnBVNiW5ZhKbq4HKIpOvHckrsPm/0kLWXIk6MAbmQotsnKbra/GyXqHO8/pbxwavZ8n4ixYW00RI6TW/FhNRqLy/9dv5Yr8f5f2yNY2oPuVqi7Rs4lZCadqmp7/Ov8yT+3mN5Jz9Uajpz7NTVjU5c5UB8JwY1YvT01MSWvk5fywV6I7knDSB7GqSprH4OAluk7SsUFzDVWGGrgISLKlYA6r7RK1fUzJGfHvZaKSC3bKWkbxlvipjn1oIxWdjQrjywchZORlA53d5U9XH4iq7VLRXSPwsTlefHPfk6pH9iYp8rsiHT6lecWUSPTzrfzZaJWK7XE40LG8XL7j5K4tWNrcaE3ET3234lU0Aw4NkHAsDIq/i43oH5XbnKIAbMI1n0Si//zBvgONu1fzRwfdU9E32Z2V83DtWb9+/vnz3y4efL/NmyFVvxY3Pm7Bak8X/1BimskhPDkQc8Kr48etwNmM9+VRY7T9Jm5kt3OI1fNvve3Et7OfzwtNiWPUfnz+LXz+bMqx0f9gkzr2+wTk5Ga0SfQ3tXbS6TSZ8KVHtQHChwmDkVZSnSL/33PqmzBg5DOHj2ySL3X4k02R58/O0UEZHYaj2Y6gssnT09soyJpubrXp/RTkI+jXBj/FkMovuCUbv2GvJHBaastwx0d+zZ0JVunyT8yASh29FnewLTEPyiIXNTJO7SD8m7tYdhbM0GQXpenybe0NLdm9eBN9TcXJRBQ0XOSuzGdV8L9yWgJ2RkCzwDfsrIm2TXn/9wPfbqr/llfdjcfUye/9UX7imMV7G/5Sf0XyNv6QDGphIFSH9+xqT7pFzIp6ll1MP7uTjvWhwMzinWq60eyYfSYU0XvUHJ2y1ZWNHomEy6YD9aHJjSZSmZ/r7l38oMec8gAH/57/1+n+e6UUru/ZFDkY+yZZlS1eZju6yxwZ5CbLz1VXFkXD9zXlFg7Kw3L+SZ1ZV+HCxmKkhNo+eVGz2q/y5d5PiW0j060pK9S8UEsb8LpyHN9w+y0JuPpDKi4d/lH/ltSxm4VjI90gKo62i7JnBL/q31+LhvJox+afzaFbXnHyCSg8PRq/lB5XGybuyxyFJaH2NxoODD/z7a/7VqEgIoNQEo3UOA228gkV7VCydDj7w3/9QfxoWOZpOyayM1J3aVKWt0Upp0sFb8fQ/sofPDQsZTvIjT2H6MB/TAvD2a2SJx6XrRbTs9QdVma7K5bD4Z3EpyWRwmP1WeqAIHvLLxquyyk9yiNCCTZQanfWrb89gE1VdXBSNNbUWBp3aXvWjWFDS09IbSytpWQ+G5Q+Kj5dEeFj6u/hwRS6GlU+KBfjads6Y4zDQKL+Q/i4dzsK760l4UVT+wYyvYF8Vnjw3o5lFhFtABfLX8hNm7Vnykvq7+KzUvEmcLuTCbxWLsqLmj0ttfZP9vbH46iqHolX6r+IzhpUYGr8XHxLKNxT/LU15wlCAVYCKDi0DNSg8YZ2AF4GI3wosIHyKZBpE1IZAop6zNDvSliYKJ/Dz2Um3VKz515FRIS3TZIlIkP5Jj9FAJ6LycUJ4hLFGAZOLRquqpCZfPyjANZL3gOaBbuFQOWC5CuUPdMKMiIEXButMXmF75nsZenGoz4Tqnnnejloqa5J9n7W7IqRUk4NBfNtKLQTJZ43nz2trKVG0tq/NwhF4thk3Z33NkgqtdfsKdFBnLSmzSnVVaHFat6ZEEtK6vCZZaF2wlCZ61voAfllTbHtJZxum/pXqtqU/nG2WRVKquXE37GwHe835O/80rTfJV+Y8sesaT3nX5pw3qvhaAvYRp8vkjjyy5XoWif3AaMwVLx8Gxi7rVBcY5ZWNuMQono6yEqW1MH8ykQ87YawHdhK4Nq+SPJPs9+A/2z1/uZ5FRWSVr3z27aiayi5OClW9CN5NtROqWkeusBzbVLupk/MsCEQrH41uuJ6tStUYFdzfxrTgkhOd3KdiAheL3Lmm2vNv4nmplkn0NbhLJlHQ4130WXKTSj+eHEy2bqmIe0azhWgIeebLUnla8XidpiZEEgQ8CNf/Lk5TEV4w3fL+oFCYG1qRAO10X1RmXA2Ix9i/keOVT0GvUlm+JJPtPrd+Hacj7q8AFcPvCelF1ef6J+UembeRVDp33l4M+86BUK1v6uVISc+w2pym7qgXWQqWwLUhisMN7EAWesqLGMG7AtaUCKsQBqJypebs0zWmDjoaXyzX67PiFT9zwOeYhEWoVqr26R+CiHdr0yBMZa6JTjRJpYLJvX25uUsf3JnQOWaMPHsIXrLiThIJuqmMCHHTR2tZJrhSS/1VcL8kc8GWX1qR+3g2Myok6DERBWhebmK2J4UWDYKf57q199HZbEarA6egJDIEx2aBN/uNCjkaqN+ZyurDYp0itBjqnAWqTdR/zl2REUKjtvBrErMrsVo+sLkRLpD0MrTnQh1a3VarK8tM9vVI9obdCO3BO9wJsQHC1CsWX6HGax9UwVZ1eXNnDomNfC4utvXPaiMAtc0wMNs+3q9zSBkaFMLhauNL/nHh2BSwbOE0R+uLHazG68uKmzejrJkiQKX3VUgyVrrRwjleRtOL+kjRZVTYA9KpVVzruxXn0iRLX0c0H4DT09N3OnQv49bkal/l8eCBbmv/Smw5lrgi9I7JWJhQHbQrjsktQVZSy2G1c+qbwf8rf1bXmlJgQ7yqLrqRx99oOIfZb8WH+o8Yr5NaPjxVo3haDpWI4ZJooCYEeinG53WZnsOw+FK2hFWyRVzIoEThHYnLaCmqGhkn90ZfotLSWeEBqcbEBqORMW6jczsEH7KyGe3ltUcUS4sARLaeLbQ8MHgelNrX53Q3W0n+9yByGcW3ZUWj3o5XI/JUTHRQ3MRQMmjTvZJ4np8UZ/UiPxZtJPCSjedWBuKHCkM3aa3cUq1HFE0qfV7YOxf7RL/++u7N589FZb8U8Eus+TmBEak875bxYnemImzBDfl6nGJo3lgnTa8RRxNOHFelXYyMgkkOw5mYVBG5k/OTMUwsJgJyiUVV2A4CJrQMTqeE+OerrGkDE9Twxhu3kxBhT8zsYEGSkd4ma5p/ud0+EwHJIJqna5G1yvWv5EZmwSSLvUglp2z3vkZq75E+Xi3D6TQeDwzlEpnIQgPK4e6B2gWg0iNqUTnTV4tQndHSz1jMVT8YDg3NE4qbj8hPP394exHwbmywnhMADqRyK/GU26XperEQiKBgvV8EPylERVoSzwV6IzlYLwLhcaUCPaqdU1H/RIVZE/oiH5hZSBPdSOznKcBkeAvb9OENrcc3nDdRtlakXXZZ5w2R3KuOp4HelR/mgday3zz/GpI4k8iJnscK6CnkLEWLU0+FeAnhmwgpKXu8GiJfr1dyxFa3y2R9c0vGlPzgPNn1kuW2VJhRJfWcd7glXC6/9zoiVczrkJvlpUpYfMU+ie40zd2Ed01o4So8Su44LwnKF6+uuad/T1ZiB5/34IXpzILtEvXOyRgX3iQx7GmlpumpRE3B2R/yyT9FqrkubSYQZDnc1VpO/31u+fBNEjwka6X1wfUyuU851zS8DpIFDZZA+yS7M9YH0puUkY2lGk6yZ5039POcfSzpLeT2yPieAx+kOTfCB/l/inX2i66ucKYK64pAo6HE6IP3D+kqulOIveeMRl2vRl+/C2eL2/C7gfIjGDO/k8Moh7jXrwIhpWBDqwdfPzd1vZLLrTAhyvGWplMkiLN/xsqf7/XOimqodixObIDDB0yagPK2vC4/CqQzYJ3qTfX7LYGdJWwiVM/Si2U45vFOF+G85xgHHoLh9PQPnYZSGp0/e2elr2IShv6pZVjpJbK2U9HxXl+tw7R8zh5sJeSaPRfQMyCxJ2W9ExuYafDLAw0hKRsbTDZ0PAnvRdbaoFLNQjyr3enx8MNybYmbzSJqxtA9Rh/oZ/QDPzR4/ev7Dz//+PayNOQXromUqTvDILwPYwUECFs/XEcyDPMg4zv2WFlZWkvC0xQvM6BlTXZZYaOv13fVMPglXMqzgu9XS7b+BbRmeXODX5HPvr3vVk9iA4+i6lmYc5B9am9ErrBSeGsDGC6N9rY9ZlOHpvi4H1WTMFza9nEcXmutP+XtV6UFx8rdFzcUG1D3ovmkV6nYXRutHPTghUwwnCSRPHxGCJMP9hAeJfDOeHycLET4bbxe8hI8e7ioqTGNouB2tVqkF99+e0PSur7mLINv5Ry/nERfv2WYShDtWz5HE6Xf/pf/8V//x8BZ4f/2zJuT8rdcz0fT9VxsgI9W9xzdWyU6aSUaySSW1D26ubtKFcmAU0+nvJDLrspfiMvh67KAS4jaPV5mHN6waOrVtcUatbqy/jQ/Viv35r/qoAyrH9VXUyOXmTus7bwxHTXFCN8U/KDgLzlbVv0USCRlcHHV6Fm/tqZiA0psXbZ/0cyzcSKCU9+wjczGeBaF5oZMGScWE0ngtMFpg9P2ZE6bM8ELegm9hF4+oV5acySfSXDF3rsjDLZYBwLBl62CL3bhaheMachKRRhm8zCMr+4jLIOwzOOEZexG+EnCNPamIGxjhm0caybCOI8bxmk4f/MskWq5l0ePWEsDAuS6Q+RaFjYg2E4i2GabACQLJPsUSLZsnDuAaMtNArJ1I9vK2gqE+8gI13om/LkAW1vnjhHPWsYBMHY7GGsTrR0lw9XwLgDSbgFp/awBkCyQ7CMhWZtZfhoAa2sJcGsBt1rXUMDVJ4WrmmgIiTxI5EEiz9OdiioSdz2X01GFXh3jKSlzAOAvbndaqiBMuzo1ZeHBg4e4uYfYpPFwDeEaPtIpqoLpfZrTVIUmwBksnKoqrozwAh/XC7SQuz4TzFnt2RHizsogAHtuhT2rQoU0m44gTh99B+oE6nwc1Fk1vE+CPKvNAPo00adlfQQCfRoEmvHVPjP8qft1xOhTh/CBPXeBPbVAAXl2DHm6NR24E7jzcXGnNrlPijqdW7fAnOaqCMT5uIgzv5oAyS5IdkGyy5Mlu1SuZ4M+Qh+hj0+mj47LAaGV0Epo5ZNppf1i0GcSJbV27ghDpbZxQLx0q3ipVbR2lC5ac/kuIqmbR1I9rQHCqQinPk441WqWnySmam0JAqtmYNW+hiK6+rjRVY/b5uFQwqGEQ/mIDmXZZED+IH/2uWF7N03Wcz/x+3XOPshteD2LpKNZEMe7h8XDwH4R7926eBTmSW/i9cZqj39rbuGuVo9rTD1cV1nO7qxu4qi+ULfP3kfsZiV3pCA8GGwxViQIYqZJZdSiTutspNflUjXS2tzf0rDd83LNFujKvL+dQ03r9DUt5oNff3r1j1fvfnj1rz+8vSJFLNUkYiBqirgNZO7iMVdKfg25WPyFfFkRGJRqWSVkWubkXRBIG3/5dpakqZjpZD4Xt57Eq4fiqv6iVMGHn9/83LuO5rf9C2rI1ziN1RXEk2gcC2tEM0qtisg4CaeJZiZN5tVm8HgGVwXN6V9J4WE3TdxEHCRsi3iQ5zyGy6hUzX1EokWwhcAYQ3A1AL1ocDM417bznBSYHOTfKpcklzDSeRCtxv1i57mNo2saqGQ6tYYL1XeDf5U/S5JHoIsGmgNPF5Yo10eOa31hKz9dz2Yvp4QAb0hZbi5/eS1efB6k6lrieFq4utlS1z356XdxShLIOK4XD6KBeTE0r05sBAtXQluqkZdER9Jx6pMzz0sjTdM8uQ9uEp41IX/xze1KTtCAY3WWigi0RiRMNCW5LyurUtJHjZvfpMEspgGQjpOlFu1c8do0n/BwUANXtwNLTElcYW2/jlp3nn0HrvXv63BJuJxviL5+CK6U0b0aWAKj6+saoyP1txjseU9Feu7QFK0qpGezLNhF9mCkP1slbs/Xfjd3OJmQtU5dl3M7Aku1l3W7ylgu7656tn6fVj8RlmAohlsZcntHvKJYtJiEJDOhjp8NVomYqJH+woYoqm0iC3tx0hjG4JZXnpJeVGAaeQZHr+LkcjF+yziHo2oC8NhfQeouvh2wJe+JS9KbVwy3+5w3VZurntt959hKPF9Hdjea17Mxu8Lxai3ut49kS/VN9JG2N7QYRvfn3BM2IdTdkNeHWci31su+nbgCNus0C4Boe0uzJ78ZCcg14EVixB3q8X/6rkFUtRnq7x4kCWk1WJdSqACsfJ2srF7D5DNuDZGrW+Ea+FZtEHLMyw7/FMPobo/4+qSxHY03WSOq4eVVChwjcWG0qVuZeS5y7PfjUgrfseBXkjaT/d2Jd/lcPMvNghgtLvn0cGnM0nBs4NjAsYFjA8fmYB0b05zDvYF785TujSmLT+vkOFvymK6O3/3PgGyAbIBsgGyAbMcC2RzrAtAb0NtTojeHWD4tkPNp1ONiOtsN2whnP0U42z4XCG8feHi76fJjqNpTq1p5TqByh65y9tsYoWlPoGm2qYCCPS8Fs94ftSn9HGJ/iP0h9ofYH2J/hxD7sy0EiPwh8vekkT+bUD5x3K+xSY+atFq6aBCO0RMkrxbmAB7RgXtEtruUoFaPr1bVeYBqPRPVyi+JgGI9nWLpWYBaHbhaOZiwu0pakHc6azjrh9Cw60yvv8aauaLH0jJP7vu+41FPSOyR1liqAJmNiG4iuonoJqKbBxvdLFl0xDUR13zKuGZJHJ82olnXmMeMZfrQDPqcSbFVAwgHCAcIBwgHCHewEM5q1wHkAOSe9GCxTSif+IRxY5MeE9Q5rj1B3P/x4/7WqUDw/8CD/22J2n24ZZuqhDcFbwreFLwpeFMH60012nh4VvCsnpSRtklAn5istlXz9utxbXgvyC6ci0e7GAQexaPcD1K65mMSpwuGw64rPlZh+sV2vwd/ng4+0H/fCsyRl/gm/5U99OxKN3n3Gpmd70OSZ/Oh0SxJFiPOsheTYntdfpGcePFIN5uE7ef5D1T8nS79mqZU3HMyDHqz8O56EgZZzRLA5m8apVTDZD2jtrHG9atXjvg1gYfhUl0y8vNSLh2F20je6GflhSSiAsaAEm9HwXo+owkOzgoDJvQsJT/HcGBWfOMnOykygjEOSSh/W5NWR/N0vYzSfI3gdwSk/mvhbEW/xwy9snr4MkH9LL1FX8QngWWeovXN9cM3Qbm7f9NgNquNhS1eseBIBEJDlVSKiStSzDtS9M0ovPTywwPj+smiuaOHi6Jku2DV8Kb0c8GZqFdZPjGe42TJISRxBdPgxIE7eo2Xssi5Jk2VglN2eX9NI2liZzEhZWVh2VMTxckazaP7IB2Tactdk/tI5Mit07JrJiJnLNE8MAroX6kLA68EnL9S9/RdsWTcrWereMEX/RA2Z5ErVSc8XDES5Nz2aOqo7gfpV69EcI4djKwSIUbiBuG+WDnILSrVdxuvhMcYinuEylBFN/4slbdeKZzA+IYkkrH3SdH9MK91dN2coDpvMxTZDcM68/C162bFb6ofuS6MrBotYScu2l4Ey4M5ulcN2+AuWC5v/6ZiRIeVT+wFN7z/Udyiyg7/LFo5AJ8T3EtFK10M2VPYQU+b2/0rjdTQ6+rMzOvKbpcd+ThitXd36H+q5YX7mjg49gufoe8pESXh57veyGCven5XPp0HpvHq9+s7eB2R2i7l/cvDUbZYkejdxGP5seu64MzK5jdIWm6PNr4dvMt/b77alKQpTIfTM14kgz9Uxet1PBn8+uu7Nz0RMxyKrgr1oM/FT36i/+dZw9WjNXPXb/LVlPT2hFaZl4QKk96vkV25SJQKWJ8vuqnCPBBofE2GOeIF9q3bP5XGlRAym0sZpwylNc79vbGuh8MvoVy0l4O6e1SFVaqszLHENKOsvp5jPpquw01p2WDg1SgU4tLTxqc2htt1lTkgeDYnvX5zw/oc8FAeab/pdtxa5bCJohzHvs/Vw/LRLS6hFX6Nh+ha5kCNPq8E6qOLepdXXFpO4jE9+0PXkV/mJwMWo9F4FqbpaES/3SUMzUejPwdej/8HIV1GSFTgrL1G5VEWViy+9TqextQ5uR9QU59oUTCNZ1Gt4hkDwJeHS3Cg3zJScnj9oC96HxlYmGObvdrr2BWQPg8+ffZWUXXtsBpYQ5yfVGClOJ6cOIOBdbBQBobFlxoH2k2Dvo++8dpKt2Uphn6H4tW+4eAcjFj8aobaIvpIOGBatMNZub73bff567hiIU7W3RfjtR/o15/oObvInfWdEWESxaH26c7rwK1423Ab7K7B8NCNiF8EhL8WIV+OLUcgUChcboCIT4Q6Kv/LUcnVer6KZ7yfxqtrGvT41NJVqYEDYU1GItwWf43IU9Wl+o5q2dOLGKOpfTtRit8inELhK/KFrfnrHfXE86+JlLiBI5CeNangigwt7sm5Xw1i8ho2WLQZYwttiN/IV2z7dVvj+i6pAwobiBYjavA4UQMx2AgaIGjwVEEDhwBaYgbKLmwRMjBreNSIAfxr+Nfwr+FfH4N/LQHnsbjXjuUL3vXTe9dKEOFcw7nel3NduC7ukHzs4k11cLUfw9Wuv0MKHjc87sfxuJvvMis53pZrLTfzvy0VYeMeG/cILCCwgMACAgsNgYUC2D6W+EL9Yo0ww9OHGYpiiWgDog37ija47qlH4AGBh7rAg/c91ohBIAbxODGIVlerl8IRjrKITCAygcgEIhOITCAy8ciRCRcwP5YghfdqjnjF08crnMKK0AVCF/sLXTx8SDKSGDUHXQxcNF7pjVDFfkMVFjlBoAKBiqcLVHgJpDVMYSnpE6RoMEE4uAAvHl48vHh48Tv34m0Y9Xh8eK+FDh58Fzx4q6DCf4f//jj++9vfJYqEHw8/3sePL8kL/Hn4893w5xsFs9GvL9UA/x7+Pfx7+Pfw77vu35cx7HH6+Y0LIPz9rvn7FcGF3w+/f29+P4nrD8n85nI958tTvo8ICsHdh7tfdvctYgIvH17+k3n5XvJoc+4tBbc6WFBTIRx9OPpw9OHow9HftaNvA61H4997LX1w6zvg1lvFFN48vPlH8uY/LtnLgDsPd77enZdyAn8e/nxH/HmXQDY79LLkoe3SCxsMdgCEIxCOQDgC4YjDDkco1H2k8QjX0o2AROcCElpQEZFARGJvtxNGq4+3ySwS0nt4txSSJUMoYr/3E5oCghAEQhBPFYJoEERL6KFQYrt7Cy01IXsA7jrcdbjrcNd3fX9hAZIezT2G9csb3PMO3GdYFEy45XDL9+WWfx/Gs4/ku7wVyxb1HUkC8MxLnnlFRuCdwzt/Ku/cQxgtHnqlFI7vwy+HXw6/HH559/zyKiY9Ft/cY3GDf/70/rlFQOGjw0fft4+uVih46PDQHR66E0HCP4d//rj+uZczU/LOVRn45vDN4ZvDN4dv3l3fXGPRY/PMnXYAfnl3/PJMOOGVwyvfl1euR/+gctl1oy8VoIRjvl/H/KPTdYVH/uw8cjlcNXPuPUglR2Jzx7e++g0HrtnfgNsLtxduL9zeZ+P2ZmDv+fi75kf/28IzooKg6egunkxm0T2BqsFd+HBNTiABm+l6Li4WH63ueTCpbxq06nXDAxXV4AgXjDnfPZCyTKdz3X8RfGSYeR+dLSOjjYFqI33hKLaIlnEyiXkBeQhW8V1EMLQMnGfJjaO0eCoM9HAFd/HN7Sq4joLb9fzmPIgH0eDcqUUvGJEvg1u2IsH1+mbgxGW5d67XURXQ4C/da0A90G0NevaCSuyf6okYiuWSrQhbrurbhJkP/juPZRpRJyaptbr7WzJSwYflumZJmAibsIjmE5YbDR1Lw86f1Y/kJ56Sz/UDqXo3VD83AXIvgte30VjYb5L5r5GocxJwbdzb8W1NyZRcrdlEeL5BMh6vl6qWZZ2xr+pUrdGfRfMej2ifnfC/1ttlWsaipXV22QPVoqDcO5aH2tpIWdkdIrPIDArNAGl69n4Vz2YBTy33bkoLoXKr1VqTWangrLG2M3bF1QIRhFMO4Syjl0tJ58B+ehZC0KN4tgWG0mPzL8NmHTBVPZ6voyaQr9wVXrF61VZM4zlbTPvEKnUVNbAQ9GoWZvGQRN+9OnH/KZJxr3C8WgtbLfWTwYuwkGSy42lNeRmAiFmmFL6jRZINPDXwbBUQ0AjCmuJKnKR0TfIghFFVmNaUn0dfhSisljH9Njkne7/K3z7mwAjBkfWqvgfG666jcUjLh1rxeJRFaKChvBht91zUedU5AOJK3HBXtLC+mgVpfENY3wOJHHtgXyxsepioUe2Y47q7WZBDeuwSYJdgX7sEb8I5NTdZp9/H0WySIncPWwQlZ7gkIdgpQO7eU+XuNYqiJXevVGYr9ht7XSDgBQEvtmmwTYNtGmzTNGzTlNH2sWQnNi7cyE58+oBDRTgRd0DcYV9xh/erZElqMl4vU2rYj1GaUvMPKlXR2gPkLT5OUMI6+AhNIDTxVKEJT4G0BCgcdmSLMEVdjQhWIFiBYAWCFQhWIFjREKywQ/RjCVl4LugIXDx94MIhqAhfIHyxr/DFJenqQUcvbB1A8OJxghe2sUfsArGLp4pd+MmjJXRhNyJbRC5qKgRjEtx8uPlw8+Hm79jNt0LZY/Hy/ZY+OPlP7+TbxRQ+Pnz8ffn4NOrparker17NJ4efrtDYG3j/j+P9N04EQgEIBTxVKGAD4bTEBTxszRZBAt/akeqAVAfEQBADQQwEMZCGGEgz1D+WgMgGAADRkaePjngIMEIlCJXsLlRyYsQvMgd7nggZSAV5lPDH1VvzoaB3L1cjsuRZpGMYnIoPTzVfUiFgIpnNTvWfpycFaxZc8mzcRQIGFkdgevpqtWKqCDl3f1Re/Kdcus7+KEdw/jwLTktVJfPgTGui5BULJkkkvf7od/L58wJqaF5oX0gvhWOlq6lcRPKYwGj0WtjOvPk8YfkMeDn/y1i6XUXlFBN9ETg9KdXEvIDylWqKyLZqD+vEElyoZ0bsBy//V0YoJit7q546cXrSoh+0ukdc6VibOlpaw8mkpx1cKdWEsQtFWconIzUQ+r3C4JLg6et9MjdUPHceEJyP5/EqJvdPfDKsvERgEEer+v3yGpv5/lUlNZmZcxUtS0TrOIBsttF5lykR8zhUP5u1/sTi7X9I5OCZb5MNKA2Ea/2TxHfij96JK3JS7cCnRiGVJUsshMU+iZFXtKFsUZTMaivBmEIsJdWGSYK9ofxRbZ3h7mcm3jllhvUZnhW148wnbOcVw6oVnL4NFlr11AIAhbA5xEzP39A9kWLNyANV4s/qU6RiM15ZScbWCxYYo0jlK1fnbD5Z0ZTKXv4jm/7LqGKO2AfKCSCDXFTOg9/W6Sog9C5Xv4XGO0UoUHQZt3YTXwTvpPslwxf6oWCyjgRToHTVRLBduEmylScVL0xBM65JVxGTUSNIHiTT7AHu+NWv8y/z5H5+VapER/3DYDyLCUwJULVahvN0QfBgvpo9yLYMynsk7s6TKc6a31MfWvwwiQbU96VW/ZDcEMJ8CAgC3hLSnJGUyCdZcMdfuIFjWstpqO7CL+RdlocmCtOYhpUxzSS6Xt/ccIiy+EypxE8/f3h7kdMakonIqEW1x0yTyTEoZty8jhSdYnVP42qxvibf5ls5MN/SwHyb8R5/W4lCLR6u9IyVNiDkuAgLe1Ei7f9Z8CiGs0/85WfFNOssnS+ayii8sgw5x9dSbghHhPSknfsGo/q2PbKfEjGMPPRyV4f3HHiA5skkuuLRpNEOZ9SkyYMYb7HrU0XgZVkbcfnf0tHigQzwfCApYUeLJY3ySEiHEA4Xcacvx+r09FctekGPWm118bS97wc6WvPn3wpaR508U4p39u/z0+BfnO87Oxv8RhYqi6pzH66pMwOS4btwNcroMzON8iUllnq2VVixIYyoeuiKCha3S8WO24SUk2SCZzwgHWVMTsJwH5L9WSVOL208W0+ksTtb0NDQ+jzQzopcjTXQJ3DgqITJUqkFvPDMQ+ln3Mhm8DjL7cMv8ZzNp6OGU8MCnf5N8TPHqzNynNYL5sSOZovpesb1OWrILNI52xPhlES/LxKapJjDSHdkdcXS5BwHKRJOd/VOhg+G09P1RiJ82oAp7QFWUlO78BRskUGFzCEEawF+wGaMzIr6ztLmU7wUTaLxjFYyFW/UtUnxrSpL38nRHhnrra5TLs6pXEElgfpt+NVFmT5O7qJgSo4LtT0RMserv6ZaJ/nPa6AnXKEUpahXgoaXhypz3NX2Pn/u5m3Py+vNfvE+weQ+L26ax6mjDvUiPQqD4AO/nvqS3DMf/CT6Gs0S1gWnLqcs6Q8B+YJCnYvjycs6fRovgyvJIOmK23AAmsybGEpq85y7oriqx7y+iiAVc1g74/0vzBg4b4nL95Ixy/CUPXdDSbxGszKingq5dkec2/B7T09/MdaRXJF5dkvDtZ1uuxcOkVLjp9NCnx0Gz0ud/RVxV7Bi99Ci/RQ/LsTYJcxw7/Ip14aE4j5MGUqHFfVmVXXfapFZWVocqXOZ4+KIzW6PbrZHODtDOTtDOrtBO7tBPDtAPZ7IZz/opxQ9bwoH+CQ8kJLw+C3IT149kGBQr8T48Rp8+ctrXsGuozzV4W9yuFmA1mnEY12SH1YbMlI0ncZc+UcwJF1zvtGsxnDwJuLkPNF+VsWJ+FMCqXJ/CB+tU3m9QRpF0gCodVXebiN2G1bLB71A6+ArtVm896SMMUQTlJjH7Osn1ICIYcOcZjKaXAS6veoemll8R5KVTIPv/vrXUm2yhK40HQTvI6leokwa8BJR7lEQ3K5Wi/Ti228zGmtCNvzHzTK8Y+15ebMmHU/l9y9lVd+enOxnhfFZWdotKHZJn57+IaK65mT3B6ORSjP44+wiOAv+heRsWXxEX51S+aIf/K/gr3JP6OyMFi/7a08FhqT/aSkSd0SoJJ/CvOfTrqbzPBcS1hAySgsJ3ahsNnW0NNrfa5OEzWbetfb6r7nFcWtww7Zc+TZf8Ta1sGbvnHLwlLKwa3moD2j/a5hGb7NLUcI0vyGlbIl2AXkP1xBlw+KwQvn3pgnKP/W0P+0xtb9eG43pqlJvDV+3hq3bwdXtYOoW8LQBlm5qLJ2ifxH8kX38p8vEWO+4cm7JL6O75Gtk2ZUXxS0XOfIY80ZEdmNjugjnvZMCGqTR4502ArRX1v25q9ze/U1EnBTA1VEoI/8kWqlsvBG9Kis1FOcdTvKOG/kZ9ekZG6dMbJHX4Z1twf9ulovxqPyy8uaPxu70rDAR71Uqgnq13hcycjg8N98vzESh5YO4+i1axtMHeQ8Xp9WzpQ3Vr+I73m0TWTXG3XpansL16rZ0obXcvZe1ykT9oi3TaYfZbrH64DzPnpOacmJPb+I0V7ITZNSjWRJOTrkPiYAC6zk1Ut2ZyV/RyPNJGJFdYoaUX+TZAKvgbi2VP5XhWxGyDFfhdZiKzFbyumhmZpFReJms55OXq2W8UNFR+t80XkYv6R0vyVyQXfsb2aXrlEVM7LpyXpxhVl8EVyNuH6eziaNVY740cURF81MJq5FumEh6k3cjkuqbveC2qlHg/WVqtUzd+xIvjGCnfn2ha/lMvjgpLhMXPPlLqjGZ6j3Su/ALG2h9VZ0OLvN7m8Y0+ioFaqXGSWzI8xY4T7lo7b05tHKDdi4u1buN7gbBa71YiWshVWf1fYj3Qh3T0tyKDe5wLN/PqEGVsLbPiIO/CNbzeTRmm76M2dXlqxV7sokikM5NS0hD7+J/6rv2ONcxNNuvJSflpE8SwFlCMjWNZ9TOvn3MP/K2tByfkbiZcaQ0UjjTmVLyRYLZbZOFV0bzOJy9TKYv1XIchCuxWH4l68PZBXILQoyfzEhIi1fyqUs05XtSXr5pCGPGgXq8UyrtkB7bMTNVqqj1xQUoS8M9tz5kOxxVMALGLaMZOBZ7HQQGeMEW88PbJmqi/9I49NcRlYtGYoh45M8MMWKD0uuf6csNTZlXks2lhBngYIopgXo/ZURyNJJ3ohrFddPNVkeF4isVYJGKUcZnL7hJvPNUfOciXJIZjBf8dI9wb0zwmeoQuletQl+sWXwzrdg6QyifbYt1Khn/oiTU2zXb1Numm/MXLC82thsvXAl+nqtir2+tYPBLuEwjTkd8TxpB/pClGQP9sDVjS3+Zd6bpiGZJ6k4aD2daT0CdOzNGhtZ8EUPN2EEyWnFx0uKAqTTIzgOz5yetcqEdj9f3VbSSQEmyJCs9NBFJ9mmvJnVf5fzVHk5x5QHWghv7Vhs1aWhCKa+0UEs2uCWJL5/CofF79UFGPbnHkCyHfB+1LW/wP9aEcdKGR4X46LxdKQ79i5Pq9qO6SbloPHzybGvya2sHb7fHj08cicOyx4PszJCqwfK8Blu0Bgm4o3Gm9qjSK+naivNgcl2hJUblrIsD/ZZdthfBvcCJc3UrsUqgI6zMKwIblFNyxOcEL8ZBT2gxveGlWqIIsYqXRemJdTteLIuJTEBgwybC8fy7rpFeQsrDiKzPyDlZTkSaAJX9XaySTpYEfed0ZrgZxYncuPhmTqvyJ/ncS5qadfT5pOwQpmQFxMm6es/wmx04iUqbbU5i6cxUg8Pn8uxMj25NMvTJ2xv1Xes+X2zu8pK+Np4u0xbQavj2egir5D5aoWXzySq7i98/2QpddMfrhrMNZxvONpztPTjbeh3+C29qRcUzoy+4sIYlego0quG4f8poQsEb7WhrQTZqkVBBnLZkMiDtC/ZIBOV2YhhcSUm9OhfJCtc0PPce0gD//9n5/y3d92rSi1oIhKwLldYSbsB19kb/UvKR+ciT2Ky0vVAdYyeMPBwG39lKmoDR7GXhWfOhAe+i0NzFLLnMtBCy7ai6UYUy1ef7lr1Quy/WnGtXxcUfXr3/t9G7NyMmyakjBVj2HJQ6dYP56a+fDVaX/tanqA3nRPudzyKWc4DBHO9ABqI+2wdzNonliPx4vQroS9SUEDBHVrrtuWlv3rT+oC6ApMnQTM8+P2quackc7VCGvzLD0uror70iRXnsq2osCxqoD786BtDjJG/jaeD8uO8n/vHZL9QllykdtZEUE+Y6tXVwrGkhrF/ZPFfDDVfE+vWv/lTAtqtjwwrpIDmryfI/9zxnaJmj5uXR/YSi5Hg7Xy0fFgknN09FEtL8pSZTIV9hxUyVmlSG/SqOCXLAIbjhNGrxhQL2eTBwT8khG8fw2mZlKHmwGodShHEgjL3Zsp75R/+kpE26eJGfqXBqj2lS1iEtsqtIplVeqXddDQoOYTKfxsu7LIFMxxtEYFicc2MQIIO/15EknRH+dcGVU5MxcPOMqLWbsd7XaKTqVCHIxSwci8ytkTzbPpBfC2cj5PWsqon2ATh3PudYaTzYC7LG6ay8V/kra04MJGkaMy1ARmxLzuYymAh6k0mkzqtxEpXRg+Ddm5PyqbdQJrmxxygiiOfiZJlIlwtnaRLQ4k/+efl1cZnEV02QIDii9Y1aE0gvWcbCdB/5t/mck/DCSXDDlS4WlcPzet/AyKdjKEufyqRBo0epbHTQu2fRiSq948MHg5tBIOI3wdXymg/Nfb2izo1vwyQN7pL5l+hB7FCQH0wmIvhenXus9C9MmSRCkg8IHFwhZygd3BfrWGHREIWdyZrCRLwX+W2vk0k0+PWnV/949e6HV//6w1sLeDs1xCQ4+8Mur3+eqZOh6/lkwOexHpK1Je/1lI9kjFlRJzxHgkXCqF1Gls9VlkT4wHqqoy6Wyrh4KtJTWc/TFfMkiOHlrLXTWuoSkfTKdNVzIUdiaMXxVhX9exC2n2mdB6bHb9X9vyjlV7oeV5g3dIT4p58/SAoORdItC5Ak0Ar/uFP6Xrb87I9iw/88y8KLZkfzA7+nlrqUQv5Nm9ezP2yjJKre4aRkJS3John7xegunkxm0T1JnabvWc9HWQ7p6p45IFdJxval91ZLvrTYz6OSxdFvTqrcbLG17YE5MjFtW0WlZMwiz5WNfZrE2uo2uENZZZ+7SlytnG7XFqjLU611UL28Txs0Gpp/+GLL2nSZ0gD4bEC26urjskLWxRC23KB0j6+Cf15+VIF/VIpWnUTVCketGGyYeNFS4ErcFrsgm5LrzHaEU9Ujm67mteYnlrn0hhjT8Kj8ejawBvmtFx3ui+AntWcj6BzsewzyIFVld8Qgx1B7KlfVZXbEsCtrwJVgYLIdwxB5III2SrJraF890L76IPhZblqqEbdU4my+rkPzJivirjEtZpakFfJ/1M6eAM78lDz/epukCkzLP6M70qCvUSEEa61PoP/4jnfV5e6M0FAhSmk0V7trJnJm8lNa6R9Ih/9mqS/lLSHpFglO9TOuc8b3MERy4EQCAGFrm2jnR2NvaGrW1xyvUYRXL/lkHMHr5Ns4TUnxv/3vf/2f3524qTPKjDD56pcPCEfvm9e/og0rlXfukVSUQv4yIOUS3ot7mayEgoaqaOWL4F+yVpkyxWolpL0+/pQb0nAyEkSrIUMovWbR2CfLSTwPyZ8dlZ45b8nd0HdE5Rp0Uv5wMU+1xPWbHajfx6F6z4P1tZba95CnfNcv4l2CkiYrY7xXdEZR2+W0dmIn3WbKVFaI3BY2D+eZVXJGjeb9UWfVbKl9wuWgkox/pE8s6xdhNh1ImCScFXH9wBA9XM9WtlOGvN9uMR4sYfI/ymx899/+5//9f8mgREptj+x8RC/0/qvYeuXzg5KWT+dHKCeIM1ZUtkYaTi3z53Om9Sw/05rNzr/PzzY/HNrrb3wqVx5n/VR3RLZ4TvCzV7z2RXCp2JJKQsjzf6N0SA7CX6qFnfmroqTgTbQok87yss5u3gIZAipmOWQEjdHv0XgtTu5+jUMrFSE54b+lPnprPTmptTPj23SghHOgg+eJDjbdO9pi/8hMv+o6asg+FgFS93lh7b+KXQnVkp762b9w33Ihwj39SlL3SPjU25CwX4p3PwYJuyiyJQd7U+Xl2FXFMT1MZvXSLG+WIHC0xOoF2ThUXnXx8ylp1bOo404DRWAlBys5WMnFT5CS74yUXBpLcJKDk/xQOckrEgxKcsugg5I8rwOU5KXISVcpyT1U271sgJG8C4zkO8MXu8QY7vAUCMlBSL5zyOMJe/YCfWzn0MBHDj7yA+Uj1xIPOvIAdOR7pyPP7CvYyDdKVHm2bOR+Zghk5CAjPxYy8sxU7oGLfBGm6eHSi9fmHWyaC7BFvkKnycUdyQkd5haXgg+2M7Cdge0MbGfVfJ/OcPqYO+fe9Mya7CY7Jt/MguPNgOPK0/Env/Egvqk9dthvQ18k7cD+6ItyuqF81C1cyDIhz5ntVWZAbs6H6wgBstcJThtJby2++mZ7qHWQFL3FRL5nz9BrMyWPStBbGO9u8/MCsAKwArACsIKeF/S8oOc1hQP0vKDnPQh6Xl9XHuy8u45NtItPeMYoGuMUDnGukPOKXYgjYuetCW6olpkuPbh5wc0Lbt7myNvBcPPuZWd158y8ji1NEPNWF3MQ84KY1+gdiHlBzAtiXhDz+hPzOtZa287XgfPy1rg+jVtyrfxOGy4CLW8tLW9d8MB3V9KRvOce3i1ZeWvkCaS8IOUFKS9o9xyHx0HKC1JekPKqd4GUF6S8IOU1yoOUF+gApLwg5XWQ8r6PVq8mv8kUr224eR1JvHvg5jVbvCVFb0aqa1SpdoGfHS+vfaI3yxA4WnreouwdNkuv2ZenJOutUcLeSav8Co8cDZl+keWViD+rT5HqzRI+Sz4ZrRcsQkaRylettyzBOQzOYXAOt+EcNk0DqId3Rj1cWAHAQAwG4kNlIHYJMoiILWMPIuK8DhARl6JFXSUi9tdw9yICPuIu8BHvGnTsEni4A3SgJQYt8c5xkCcW2icesh3DAzsx2IkPlJ24JPggKQ5AUrx3kuKytQVX8Ub5O8+Wq7iVUQJlMSiLj4WyuGw4wVxcys7wSc7YMmFii9yOTvMY23bqD4LOuKAUIIkDSRxI4kASZzECviRxeqL/Aka242Nkq2NMta2Qvf4uiN28Dpx2hsvLklzizc59EIxe+yXqakgjrAU9j83X5c1ttjWx1/kmzF45V1WBQdw7c7cjROJbE1JpFPZRMZhm3I/KBUuvpJM7npF3l5GaKi7Tc8YJ97YTWPcCQGpOVJWARyCalwq2Mafkks8Jd4yDnlBpesNLtXYRlBUvi2wnbAjbiPVSE68wHQqH6vl3XSO9hDSJoVqfIXWynEjOnmn8u1g+B64j4pr3K7PoDO9Ebp08rPtJPveSpmYdfXaTtPu4kt/szKs8SMp2a3L3s2dur7Hfj0rg7oAjHeZxh6cOTx2eOjx10LkjeAA6d9C5g879UOncW4aAwOp+DMGioyd3b447ZQ2shAJA9Q6qd1C9N58tOBiq90dIRdk58Xt9Dgj436vLPvjfwf9u9A787+B/B/87+N/9+d/rl1zbNtqB08A3O0mN23ytHFUbWAIbfC0bvEfQYcudTvcob0kK3yxd4IYHNzy44cH+6uDzADc8uOHBDa/eBW54cMODG94oD254oANww4Mb3sEN/yGfxV3RxBtVHhhX/IYhr2fCHt8oCptlI4BI/hkQyTtk4yk55bOI5k4DTyBjBxk7yNgd6g5e9p3xsrsMKijaQdF+qBTtHjINtnbLNICtPa8DbO2l+E1X2do3Unb30gLi9i4Qt+8RlewSmbgDaeBwB4f7zoGSJ1h6JMBkO4YHOnfQuR8onbtbB8DsHoDZfe/M7jU2GCTvGyXiPFuS901NFfjewfd+LHzvNeYU1O+l5IuWuRePwAJfl7oBKvh9UMG79AVcc+CaA9ccuOYsRgCs8KoGELuBFT7Tww0oweqzXPwJ4kVatCmDrlxo/57vj0zsCZnB/JMIa7HTMyIJ03RONpowx6n0jdJ0u80an5Fa1WYMbUb0lach1/TWHO4GRrC+x4Fwq+WzEba3dADB3X6E3O1+RhM07rbZgpcNLxteNrzsfXrZYHSH4w9GdzC6g9H9cMI3IHdHCOe4eN5bBY30iWp7GbC/F2YY7O9gf68PDx4I+/vjZqOACB5E8CCCBxG8sciBCB5E8CCCBxF8d4ngW3lRjduHrZxaG24CJ3wtJ3y7WIXvDmpdirR71LfkiG8leKCLB1086OJBCOsgFAFdPOjiQRev3gW6eNDFgy7eKA+6eKAD0MWDLt5JF//wIXmtN8dflwMC7cniL0VbdsgTL8mDBhnxRXS3WD2IMm/5t02p4RuqfYZk8LUTvVnCwnOngm8QksMlf7fIAqjfQf0O6vfnSP1uUXYQv++Q+N1mTEH7Dtr3w6V9b5BokL5bJgGk73kdIH0vRWG6S/reWtXdywoo37tB+b4nPLJLTOIOhYHwHYTvO4dInjDpUaCS7Ywe6N5B936wdO92DQDZewCy90cge3fYX1C9b5RE84yp3jcxUyB6B9H78RC9O0wpaN5LSROtciba5zFskWXRBUp378SKTpO423QB5HIglwO5HMjlqrlKHaJQcm/2e/Nfa2qhjEOgmXOoBd+QX+qRP9OQB8tQ7WHMfhvyKGkn9kcelZM95bNwXuUqksmHLRim2+b+dYRf2uucq52IuQVE+2YbtNZl5uWm9MUj4Fputjb7YFpuGPiucysD/AL8AvwC/IJZGczKYFYGszKYla1ZG4fErLxZWAC8yvuOc7SLdXjGOxpjHg5xB6uyf6Ak41S2lACjcmF2wagMRuW6qN4BMSrvdeN307Cg944rSJOr6z9Ik0GabPQOpMkgTQZpMkiTK6TJ3ousbTvt4GmSvd2ixn2/Vj6qDRmBJLmBJNk/8OC79enINnQP99bsyN7yBm5kcCODGxnsh45z9+BGBjcyuJHVu8CNDG5kcCMb5cGNDHQAbmRwI3txI7/9XUajwJF8JBzJzgnfLA0BXMnuvhwMV3JJJsCZDM5kcCY/d87kktKDO3lP3Mll4woOZXAoPw8O5RrJBpeyZTLApZzXAS7lUtTmMLiUW6m8e5kBp3L3OJX3gFN2iVXcoTRwK4NbeefQyRM+PSqEsp3WA8cyOJafBcdyVRPAtRyAa/mRuZYt9hicyxsl5xwJ53JbswXuZXAvHyf3ssW0goO5lJyxUW4GuJgPnou5rBugpQMtHWjpQEtXzYnqKPmSPZmgg9zMzalO4GjeG0dzm9zD58XV7AnlwNl8HJzN9VYI3M0AywDLAMsAy+BwBoczOJzB4QwO58ZTUxYn5fA4nNuHEcDl/FhxkXaxEc/4SGOMxCH+4HRuH1ixcjuXSoLjuTDb4HgGx3NdNPBAOZ73trEMrmdwPYPrGVzP4HoG1zO4nsH13FGuZy93qXHfsJUPa0NI4HxuwfnsF6A4DO5nL/kDBzQ4oMEBDZZHB18AOKDBAQ0OaPUucECDAxoc0EZ5cEADHYADGhzQLg5ocix/SOY3l+s52+3vo9X4tlPUz84itpZflj1l8EGbILTCB107+ZtlLoAG2t2XLtNAW0QB7M9gfwb78zNkf7boOkifd0f6bDOl4HoG1/PBcj03CDQoni1zAIrnvA5QPJeCMp2leG6t6e5FBczOnWB23hMY2SUgccfFQOgMQued4yNPjPQYOMl2Yg88zuBxPlQeZ7sCgL45AH3z/umbHdYXrM0bpdM8X9bmTYwUyJpB1nw0ZM0OQwqO5lLyRJvciR3lM4Cv+en5mm3qAeY5MM+BeQ7Mc9Wcpe7wK7l3/bvBzuyXgQRS5l2SMrdNADx4LuYWkO2bnaM38DJ3mZe52f6AjhlYGFgYWBhYGCzMYGEGCzNYmMHC7Dq0ZHFPDoKFebMoAciX9xz2aBf68Ax/NIZAHMIOzmXvuIk+rugOD4BhGQzLYFhujvEdDsPy428Lg20ZbMtgWwbbMtiWwbYMtmWwLXeHbdnbUWrcBGzltNqAEUiW60mW/QMRneVW9pY2UCqDUhmUyiBNdJzPB6UyKJVBqazeBUplUCqDUtkoD0ploANQKoNS2Y9S+WMp3aE9p7IjnXhzTmXvWzzb0Sc7ckhk89U+8nPnUP7oSG5pl4oAEmV3Xw6HRFnKwlOyKPtoZO+kVbqGR8qHzObI0lTEn9WnSA9nCR+zn4zWCxYjo0jlq9ZbnWCFBis0WKG3YIWWNgK00PuihVaLA3ihwQv9THihqxINYmjLJIAYOq8DxNCl0NKBEEP7qLp7WQEzdAeZoXeHR3aJSdzxPVBDgxp65xDJEyY9ClSynSMENzS4oZ8HN3SmASCHDkAO/djk0Ln9BTv0RplBx8IO7WmmQA8NeugjpYfOTSn4oUuZIK0SQdonZ2yROgIu6L1wQStdAAEeCPBAgAcCPIsR8CXA0xP9F7DNHR/bnBcrrK1gS5o6rzOuXWUmK+SneBOYHwQz2aMSjjmTFGsR0GMzjnmTtW1NTXa+CTdZzqdVR6/ukRvcEX71rdmzNCT7qKhaM5JL5YalV9LjHc/Iw8vYWxVp6zmDhnvbia97gSY1+atK7yNEzesGm59T8s/nBELGQU8oOb3hpVrICNeKl0W2Ez0EdMTiqelgmKSFQ/r8u66RXkK6xbitz/g6WU4kk9A0/l2spQPXCXVNUpaZd8Z6InNPHg7+JJ97SVOzjj57c9fXu5PfbONZgqf+cHjqrfYbRPVw1OGow1GHow6mesQOwFQPpnow1TtPhlpclgNkqveOB4Gq/qgiR+Cq9w9C2cnqZQmw1ZfON4OtHmz17iMKh8pWv+skFTDTg5kezPRgpgczPZjpwUwPZvquMtPXuUWN+36tfFQbMgI1fRtq+trAw5Zbn+7h3i03fZ28gZwe5PQgpwf9rIMjBOT0IKcHOb16F8jpQU4PcnqjPMjpgQ5ATg9yegc5/d+j1cdbkkvhlW9DSu+4221zUnp3EbPJlauP21HUN7Xr2dHTO+Z7s6yD505L3yQdh8pLXxCCp+Sjz+KUOw0egb8d/O3gby8oOXjbd8bbXjSe4GsHX/uh8rU7JRk87ZbBB097Xgd42ktRlq7ytLdQcfcyAn72LvCz7xx37BJ7uENb4GUHL/vOoZAnHNorJLKdlgMfO/jYD5SPvSz54GEPwMO+dx72ir0F//pGyS/Pln+9nVkC7zp414+Fd71iOsG3Xkpu8Mpt2DbfYIvciC6wrvsnQHSYdr2oCmBxA4sbWNzA4lbNKeoMV5Ftb96bs1qz92Qn+ZtpfbwpfZoyg/xpfDwofGqPRvbb8DJJu7A/XqacRykffQsxtEwGdGaYlemg/XPxOkID7XXa1EZV7IXEvtkdKOsyYXFjUuGzZyyuMzL7YCpuGvFuUxUD3ALcAtwC3IKiGBTFoCgGRTEoig+Worit2w9q4n3FMdrFMjzjGY0xDYd4Hz0lsUcgRLXQ5vaDghgUxKAgbo7WHQwF8aPs224c7vPeMAUTcXW5BxMxmIiN3oGJGEzEYCIGE3GFidh/lbXtkx04FbGHO9S4kdfKJ7VhIlAQ11IQ+wQYfPcyHemB7mHeknrYQ75AOQzKYVAOg1TQcdwdlMOgHAblsHoXKIdBOQzKYaM8KIeBDkA5DMphB+UwB+4+0iuzFbZTtMPeN1m2Ixr2vlrrmfAM10zyZukEz51ruEFADpVquCIHoBsG3TDohp8f3XBF0UE5vDPK4aoRBe0waIcPlXa4VppBPWyZAFAP53WAergUbekq9XBLNXcvJ6Af7gL98F4wyC5xiDvUBQpiUBDvHBZ5QqO9wyPbiTjQEIOG+EBpiG3SDyriAFTEe6cittpd0BFvlBjzbOmI25snUBKDkvhYKImtJhS0xKUECO/8h/Y5CQdORuydJNFhLuKqDoCyDZRtoGwDZVs176gzxESuzftOcBL7pBCBl3iHvMTtcvcOnZvYG459sw0y6zIjcVPq4bMnJG6yMPsgJW4Y9G5zEgPkAuQC5ALkgpcYvMTgJQYvMXiJg0PmJd7E/Qc38T7jGe1iGp5xjcbYhkPMj56f2DMgog9jlp8GT3FhVsFTDJ7iusjdwfAU73Ejd9PQn/cOKsiJq+s9yIlBTmz0DuTEICcGOTHIiSvkxN6LrG3L7MC5iT1docZ9vVY+qQ0VgZ+4lp/YN8jQVY5iTzkDTzF4isFTDCZCx9l48BSDpxg8xepd4CkGTzF4io3y4CkGOgBPMXiKG3iKK8dVwVL83FiKa8l4wFGs/j13jmIlBWAoBkMxGIqfL0OxEk/wE++cn1gbULATg5340NmJLbIMbmLL8IObOK8D3MSlCEvXuYm9lNy9lICZuEvMxDtEH7tEIO7QFniJwUu8c0DkCYr2DIxs5+HASgxW4gNnJc5lH5zEATiJH42T2LC5YCTeKAXm2TMS+5om8BGDj/jY+IgN8wk24lKag2eWA7iID5iLWMs/SNpA0gaSNpC0VbOLOkdFVNyk7xQPsTtNCCzEe2Ah9snNey4cxA0gDAzEz52B2G5bwD8MYAtgC2ALYOsLbI3DUGAfBvtw8aAA2IfBPlyb2gL24W67/OAe3l8Mo10cwzOW0RjPcIg4mId9giAl3mH1LFiHCzMK1mGwDtfF6g6OdXjnG7bgHAbnMDiHwTkMzmFwDoNzGJzDneMcbjyaBMZhm7f5yIzD9aGFrvMN18oY2IbBNgy2YfAJOk67g20YbMNgG1bvAtsw2IbBNmyUB9sw0AHYhsE27GAb/pgsv0xnyf02NMO6jorbvG/eYCeDsW7RpYp91DAIV5KWeC9AwiXFQCmUn4CtVig+hmp1yV+wS3qWyhDxUlpk1pr1nTTAtKyrRNV0vYxs4fOrUZYBMhpp/qYSr45Sw2q+SFZwQKs4r4xpVRvrSpFS9orf97clOq5KV+vUhfbUxXvlIvYWuUNlJdb9AB0x6IhBR/z86Ii1foOHeGc8xJnJBAExCIgPlYDYJsRgHraMO5iH8zrAPFyKtnSVedhPu92LByiHu0A5vEugsUuw4Q5sgWsYXMM7xz6e+GdfGMh27A0kwyAZPlCSYUPowS4cgF147+zCppUFrfBGuS7PllbY2xiBTxh8wsfCJ2wazD0QCTftCbND37dQDztp5ZpyCp4tn5z/5vCzZ5ZzbCPvg1LOe9S7TS6XjRhY5cAqB1Y5sMpZjABY5cAqV0r0AqscWOVqNzHAKveYrHKl9CrQye2DTq4mR9WE2OCRe2oeufr8b9W43E0Dc5wxh2COA3NcXXrFwTDHNYUDH48yboPzQiCPq67qII8DeZzRO5DHgTwO5HEgj6uQx22w3Np2xPZJI8dGJ9tOdx1oDu44XMcLpw46/cUFjxs56ZwefCMdXb0v5UXM5sU/tzHxl+0AJ5jBwAxm26ECMxiYwcAMBmYwMIOBGUxkTYIZDMxgYAYDMxiYwZyG5JGZwd6EczLbyTr9Po5mk3QrgjB7Nqe8mdsdJlD7g5adAmeRUqMvy45uO34xvalfqlVtAdaQivHCMRmp/ulaRDZtzsSS73OqLd04HcXzeBWHM1ly2Csmj4mwsxy0dHQdccOz/WJxNHdbti7njG+2Tzw0RmFX3F6W7eMPiRxF822yAf39UoE13R5+oARgJSl4Sh6wev3rnbTaV/fYm5fb7lk+gfiz+hRp3Szh4yiT0XrBomMUqXzVeqsKjGZgNAOjWRtGs5J1ALHZzojNyksB+M3Ab3ao/GY1sgyaM8vwg+YsrwM0Z6XQUVdpzlopuXspAdtZF9jO9oA+dolA3DE7kJ6B9GzngMgTFO0ZGNkOZ4H7DNxnB8p9VpV9UKAFoEDbOwWaxeaCCW2j3J5ny4TW1jSBEA2EaMdCiGYxn3vgRZMsZ46DFjrrIjtRkS5C45SEAIE0MrwtRzj2yrqZd5Ubtb+JGJTCtTouZdLNrHQWOb0qKyXPk5/kfTHyNzzTN7ZPqdgiAcQ7G8N56NNxNsR1FlRvKxk5Hg27+BfdYQyr0Blk1GFlfQCDGBjEwCAGBjGLEfBlENMT/RfQdR0fXRc1rWFZ7PV3wfPldXKwM9RO9jyTOoanYo70IRA87Ze3qTm1sBbvPDZ9kzfb1dY8T+ebED3lpEWmHWmVxVuTvVs7jPYvN8wL7W9PTqQB2EfFbJlxAirHK72S3u14Rj5dRnapOC7PGSLc205m3QvsqLkyVVIe4WdeJdjYnJIvPifIMQ56QrHpDS/VskUoVrwssp28IVgjlkpNwsHUGBys5991jfQS0idGaX1G08lyIvlbpvHvYuUcuM5eaw6ozJgzshP5dvIQ7yf53EuamnX02c3i7elAfrNLX7LL5N5N6d7PntK73nrvg9m7GYR0mM8bTjmccjjlcMpB6404AWi9QesNWu8DpvVuH/sBu/eRRImOnuTbK+Ck2mgPAIDyG5TfoPxuPlxwMJTfj5Z8smnwzzvrA/zf1XUf/N/g/zZ6B/5v8H+D/xv83xX+b+9F1rZptk/WbxLnRqLui9p980a2bi+nqHFfr5VvasNEDQTe7jOstUTexkj4bF226upetzLbbWnuaGvTPdBF3sR636rA2SeFzUvGasWlVjA2TOdoKYJ9UMSDIt622wmKeFDEgyIeFPGgiAdFvDhHCop4UMSDIh4U8aCIdxqSR6aIf89pgZek+8s0/hr9KJevwyCKtzZ9R3Tx1rqfK2l8gwxsln3w3Knj24qlrOhQGeWtneoCr3ydooJdHuzyYJcHu7zVRoBjfmcc8/bFAUzzYJo/VKb5RokG37xlEsA3n9cBvvlSHKqrfPMbqLp7WQHrfBdY5/eGR3aJSdzBQHDPg3t+5xDJEyY9ClSynSMEAz0Y6A+Ugd6lAeChD8BDv3ceeqf9BRv9RmlEz5aNfjMzBU56cNIfCye905SCmb6UNtIqa2RXmRwHzlK/WcLAQZDX2xUHbHlgywNbHtjyLEYAFPaqBlDT1VLYb7ZmHiOzfV2OC/jt/ZnLfBMda4ERWO6Lu6J2lvv2acfgugfXfckTzdgaWrmk3+zeO+0y7/2GuerPng7fx9jvgxR/Y1jTYa58xAAQA0AMADEAMOYjLAHGfDDmgzHfkel2OIz5m8aUwJt/VNGno2fPbxHI0i2tCSmASR9M+mDSbz4qcTBM+k+SLLNxaHHLLBWQ7VfBAsj2QbZv9A5k+yDbB9k+yPYrZPvbrr22nboD5+Bv4Vo1bim28nNtOApM/LVM/G2CF13l428hb2DlBys/WPnBu+vgOwErP1j5wcqv3gVWfrDyg5XfKA9WfqADsPKDld/Byn9JRXdJyn8pmvIYpPy2lm/Jyd/yXeWo2DMh6a8Xic1yHI6Wo79Ocg6Vot/Wp6dk6M+inTsNQYHRHoz2YLS36ToI7XdGaG81peCzB5/9ofLZNwk06OwtcwA6+7wO0NmXAjhdpbNvr+nuRQVs9l1gs98XGNklIHHH0EBmDzL7neMjT4z0GDjJdsIPXPbgsj9QLnuHAoDKPgCV/d6p7F3WF0z2G6XePFsm+42MFIjsQWR/LET2LkMKHvtSokWbPIsd5T5ska7RaRZ7v2SMDpPYW5UG/HXgrwN/HfjrqvlNnWFpqskF8Cb+1vRFGTtBM6+RN6eRZ16SP52RB5VR7fHOfht+Kmkl9sdPlfNJ5ZNgIdmW2YrO3LcytXbrZMGOMGt7HZy1sT+3AXLf7BzTHST3c20O5LOnfvawSo/K/Fw3G90mfgZuBm4GbgZuBu8zeJ/B+wzeZ/A+27NCDof3ecOIAmif9xwiaRcm8QyVNIZLHMJ+9KzP/jEW1dCaUAI4n8H5DM7n5njgwXA+P8HG8s4Zn/12dEH4XIUJIHwG4bPROxA+g/AZhM8gfPYnfPZbem3bcwfO9+zvVDVuI7ZycG0gCnTPtXTPLYIWvjupjrxH92hvyfbsL20gewbZM8ieQefoYAMA2TPInkH2rN4FsmeQPYPs2SgPsmegA5A9g+zZQfb8Wm+Mv5pPWt0V6pOa/SEXkcegf27sy764oD1e/EyJoVuIz2Y5EUfLEu0tU4dKGd3YQfBHgz8a/NHPjz+6UfFBJr0zMulmIwtmaTBLHyqzdCvpBs20ZUJAM53XAZrpUuioqzTTW6q9e7kB53QXOKcfBbPsEre443ogoAYB9c5hlCeUenQ4ZTt3CDZqsFEfKBu1jzaAmjoANfXeqam97DJ4qjfKGnq2PNXbmy+QVoO0+lhIq71MLBisS9kjGyeP7COXY9uElE4TXG+QYdJhtutmbQOFHyj8QOEHCj+LEfCl8NMT/Rfw5R0fX14d2633Wtrr74KLz+twbmfo13yTc7zZ3WXSuCmirkxx/zHYH3XbE/KwbZIPWQu3nhEpm6bLstGyuWjot0tN7ggnvSMNO6MPq0152oxSLU+9rumtOfAN3Gv9XVLtb+xxfrNf5/MgSfj9U8yfPSN/W+P7qPT8bQBLh7n64fXD64fXD69/r14/iPsRiABxP4j7Qdx/iJEjsPgjenSslP4bxqtUq31DFiD7B9k/yP59YpQHQvbfqRycnV8DsEHeC+4EqIIO3AmAOwGM3uFOANwJgDsBcCeA/50AG6zDtt3CA78gYEMXrXGLs5XvbMNauC2g9raATYMjvru8dWnl7vHf8v6ADYURlwngMgFcJgC6YAfnCy4TwGUCuExAvQuXCeAyAVwmYJTHZQJAB7hMAJcJGJcJiHiTM5fBmYRvJDZc8A7fdqn0/OYWQSZ+fPCK/vPZsh3mqEWFGtSWF8cjUssB7vomqI/Z2jD2+vSp/l1Z5OPz5/NSza94HkQd3IDPn40M/dPT00sxWcz1pMOHgkpKpFDqSQqzhYQN5E3MabtyUox45SXb4zS4+iVa3pGFoBJvonnMNJsxpxmTdXyl53wZCOc5SjlWrsg6gzInfzFg+8/IoJumZpt5yUn+UKBDpHIHVHCKcpCdcFL2zV14E49lQmshBq4l5joiRVrKdHXOeRtlcdeRKCq/GY2sQl8MySjLJYMwYaH71fhNHpPNlUPd8eA790KuqoaUFi0Ri8tMs57KvEl5snoYXBWut7yqMIZPogUtTJJqPckXTV7DtdUrlMnTsmgq3PFAHQvsOQgO/x5lu6pBupYiLQnTRbSmIKyDumgj2bLFg9i6lDMpTzaoLR/Oey1U1ev7pCTtPUap4pOGLXTeXbDN9aUiGUqH4l0vyI560A8bEv17tCqJF/Pcxal1YgqDPdLPlcLqhqC2yIKrHax2yVlD/1tFGtOEOLeDpG+cb5hZBsrCumsNVm50yYh73O09/LQp/+fPX843pw7lFpKVYc2MJhvXU16P7BV99gsus95m3I1WBE3rqbTStOSV4wG0sC6WyVf2aO+SZWS3loX8z6W+EEG7i2V1YK/xLhE7TqM/B+5nlGd56gj0ZP3qOWi+jLU72wfVzfvzzMkOJldFzmaYS/YhnVZxJptqF0Kjwe6qRfhJHlY4+8PQdCpCQ+0qdWWzt7189z/LQhnwrnH/ysIEL73e6MR+P0qmv2qNv+J806tzfXlIcFVgB7uSi2MUi6h3WKrSgqVyvmsBqWj5vRLJr1f9QEbLrkp6U16+LXkWhH3KNNR229Cs7X3rXuv2NZc6tYP7MAr1yfMwpJ7ekrQraXLlD27PztzGvmsCNIfS/H/JWkQ1inhckszTuD2u+lVSKLMWVY6C1x0/dXqbm/iUsv+Gc+rh4Fl9zIJr9o/8NK70SdRpPw6m2A7m5k6V6ZYp/45r6SWqDf3gyhQq/fqrILn+jYx0VphWq8l6LJMT89OG+Qunxqd8DdN1pL90eGtUQq5OJvIuOkQXJ45Mjc38Mqdv9nieiTlq42NwT57AMyG5X89WJa+hKGQD9zn0Vv6AKD+0SaVPJkdxOZTN3tHyZ1k0pHlpR+mv2tRIFC+fG2hWcRL3PMDVPA55NhFVUrHpUlVPXtT8C17L69/er9bXaVD35InKVEyjjFRoGc2ir6FKrdfB8nDMW5uSwvRSDF+gmVGD97yRdfJCf8Dnyoth/mS6YiOoq5qliUr3ZKplfuVNNBdB+IkgNxXn8+/Ec2SsT8Yz8teCURbQWV/3bOdfqKcD/lKfTyqcS5OIeVvVNiK14r7Q0chjzfRh+tAcH/9peYg+F4Z88Fb9Yr8CloHBRX33Ls38cVM3nUE0WrNLwVmTF/OjJHjOBEJH0MRullizmJZV71nKvaOztLBen4uji9n9SEbl4qBuyqlY8epBcNhmSdkv+Q20pArubHlV0Gop6BHmD1oI9Q0AOvhWOrivU9o5VXsZcbwuJnEbBO/k7X3nyl3RNxXx+r3kY+r6OL/cCOY85pd6oTWPgvOJPlb6hMzqMp7ozS+mmIgkZ+zv3B8yxuZg2A+2v9PDp1yakhiQ+3Sb3POmFxP/psGVObFXfF+KeGdKDqZYKWezB/PI+UOppzr6uVgvBXkwH+SXJBb0aSrH0+Q3EZPK6c8tUlN1mYHcLnz3ppKcWlwIsrxSf+XoW9jJ1SyILfXKKEq+DXmxQ2kIaX2cle5zLMKtLFZhfuy4IZRjzSwY8s9qM8ryoXZc370hebqOSBFKEZFsMI1mZJ/lx0Mqd7KZ5XymyHKRceEsQH6ateZIi+GfCErrHgczyoZUtO6Wz3HMyjfiDkqfF2v3vko3P1HqOFdTgjr+4lg26Cqhobr2m5IydMOkbB6G2W8OXo9X7KOzgMkRyvk4lD1MpciJIxO82yHSFm4SzW7DCTBGbSJF7JyzXqSllVvunIeScSWoF0mjdsumlq9WGi+TVNz1ZlQml+aT0tzqTOhRaU4H9JbsM5WgWYrSKmK6yvJ+ns+shSFKwV5e2PWUqcx8xVQiMEQNf5Q8b1E8Ly7QiGptP8Mq2R4nw2DxiIleNEDxwRE+4KHgF1ghhINR7D/bUXw3VJ0sv0xnyf12UOabp0Y1PlsGmQH45O2tBf40c+3y41tMSZv108irarDUdV5ho6H1MIN9feZXaVCGZDTB0EU5tCUebDytq+k2xM/KAdxihoXIR2mBcKTI/J3MxY+qcFHeNpfU0jrXok1GqcG7/Pc25PlqqMoHlHYcPzEmTqxcjZXKx9xVKlNt1Ky2RobBmXjk7MQM6tGao4+bZndtm0LyIZG8Dye1p0H6ttwFXsTLl9VU2FnEQ01BKhvNSj5arhCUi8ulaVGUI1ktXRit6tfrebh8EJwiNvoRNo/OL6WMyZCYnzxaiGJs7DriZ4VBp6zrQ/1L9RFP5CYjcjSVF67zSiaiFBf9OjKT+vWHmLjsicNxUgLVfqmouE+/qtRZw4oECrAxhCQXkTDkell3glvwFsbs/otkGMazHO7ha4E1Yd9yPSvnlZqKoZyAnDuqzMNkUZRhs+Lki5R4TcOZ+7KuDX0Uzxn71eRXdSw9nD7RoGkecmvM3ND43ZbLLk4TaX4/EcK5MnXpSp5u0EyQg3rFq/o+QjVMZ+1L9ODWEkPg6rJZDWZD4eXk8qau1A6uBuHsPnxINXdoPLUmCJ+rTOy76C6J/2nJBzcZ7GgtlZVe1J0KzRW156asKQ1IbWcL9Va1+l4pM6HW1WgWhelqlMxdR356DZfPXlhPZ5jnLmoqSJbxDSeek0cYM5EUp9tnoV75WTxvqCMLfA0W7ACvuLQid73/NhEcFFxRv/aOVxHV41qEI3tVGuwr982v07M/ikDkz8EfGj/8GfT+YFKdUm39P/tndVf6/vTzh7cX+U1kt+KyUd4evPrl7eXo48+X//b9Dz9/vKqpQdMjcLyTg3bZoIjbxyLe0pRHLGrqkPfIK87K6yiiaQjlVuVSDPe1Jj2tqWMtNgSqEzNoQSmYC6vZe1/SvxzD1G5LiQXWvmG1DcLon9Rqetkx+bB8+JBkx41fl3dUGxwVa2k4LobjIq8VHmTXX9Kzqwcxj2/5t+fhsVjFoNmDqZOeY/RorOPxVB5Og+B6ujbWLsHVgasDVweuDlwduDpwdeDqtIYaDT5OnYdT2lPa0NMp1QKP57g9npI4tPV87NIED8i5I3/4nlCpa/CI4BHBI4JHBI8IHhE8InhEe/aIyGT/kMxvLtdzPnf7fbQa3/o7QpbC8H+Ozv+xSIGH2+OWnaP0dizDceBOjqVH8G3g28C3gW8D3wa+DXwb+Da79m3KJ22i1cfbZBa9L57RazpxY5aCO+N98iZaPpMzN+b8e5y9sYjLUZ7BMcehm2dxbPc620/hmH2B0wKnBU4LnBY4LXBa4LTAaWmPMVrtyPDFq8xclV1f5O24VErCeTm2vZiKCDT7Ly6pOUYfpjIWh70FU+kOXBm4MnBl4MrAlYErA1cGrsx+c8s0/KiwVnv6MaocvJhj9WKUAPj7MEWJOWYPxon0D9F/UZ2B9wLvBd4LvBd4L/Be4L3Ae9l59ljZgWGO7Eu+4iONv0Y/yrtyvL0YW2G4Mj7ZZPaRe060zrYeNns5NRJ1jK6ObTg6l3dWJ8ueXpCtCrhCcIXgCsEVgisEVwiuEFyhHeGPZgepcIGUvBlo7xdI4aqn7a56wrVM1muZim7Qa7750N+7l49X/Pk9+sxdDhfU+/N6rMoevMPNLQytr2NrQduW+xZrkHcZde/wju2W+LyAzbcPPxQrV2j+TA5yaZXPsHzV5fWA8Q0Q3gu+Wx1g2daKy9uMwj3DGDu+Tn3XU8b/7PPVIlgiy+8jPOL0+7ziI0Xb4BkRcQjEZr4ki82w9LdlnEyAaD5ehI4l38r0geRVq47Rkj7YsOqWbVrh4wd5zgOJSOgh74DPcVyKuNGthR62a4d2a9c2S11ceH6yyUHi6mV+vtccWsGBxfFymTVnxHf7G/9a3vbXYMN8ELBdtXem1o0q/Z66NvktIr/jqz+uNgsBXfvYj+KIeWJsyzADae8HaZtDfRh422zxcaPumrlrsaCZtXQPgdvshycOrxUUoPFDQuO4CnDDPPsDx+n26/o2wu0eV9ZtetnfI+H6VgllW95x9wwAPm7TgdGw3HizA+NRe9vLtvfmHKgx8bkm5jkYlaMlpD8uE2Ijjd/McjQyp2/IOH84dsKXaf35mQeZgbKpfZClEWbcxP74XetQGGFEGPcTYbSO+WGEGq1NP+6Yo89sbr48yuqeLAq5l6tFHFKDAOQBpwMcEXN7S2r1Q08MKLCrb5Yg4GYab8vJ3omEgbI93pCS/Bmg+2PkPj0qt7/KT7qRBWjg6dyE2fRgvH0/Us9nZAyOhT7sKA2BpvjaygxYNaA9NdjBmYA6XqyDNAAlC/AmnN9Ey2Sdfh9Hs0nqbQFK5RDg22GAzz62CO3tJ7RXGu3DCOqVGn3c4bz6GWyx2JUqOvAQXpOMIHh3uMG796tkGW3Mm2UtjSXc6yiAfeh8zwTUDDzW9z0dDrCN+YGcErA1/ciPC3jMZptzA7bqOniAoM7q+J4k8BImgILDBQXHy6W5C7LLA4/2WfkuNwr5NZM+bkiW+dQ7gf5ETduRRB5mXLDEO6UYirZinvrmEEiowDwF5ikwT+2cearskDT0ZL2OJ4Nff3335vNeuKvgNYO8CuRVIK+CbwvyKpBXgbwK5FUgrwJ51T5h+hb0VwDr4L8C/xX4r8B/9YwBvRG33AgIOMoDE3QYE9TPGeDBvg6v24f9QI6v2xt/5AfYvWa0FTeUtcJnBSV8JQmo4pBRBUg1Qaq5DS8eSDVBqrmBsQCp5sEZDZBqPooxAalmAFJNkGqCVBOkmiDVfHr7s7/g5g5oORHaBC8neDnBy7mt1CCEecCZjuDlBC8neDnBywleTvBygpcTvJzg5QQvJ3g5wcvpZQHAy9nlGOF2zJ6IDoLaE9Sem8UCQe2J+B+oPYECtqf23N+JyR2QgwIigB0U7KBgBwU7KHAF2EHBDqoNI9hBwQ66u+2JLLf71XyynbvSWBNcFy8SxuZhfDx+Rs8phUuzL+rGpgk4EFbHpm4cOeFjy1luwwXZVHUHaSJ9DaAvg2Rr4YNrdEiuUYnt/EOYfkm3ojrvLr/5N6A6Pyaq810QpR4zxtYvvF6Nvn4Xzha34XeDFZsHsc6woXg3eQQU3UhlCqS8PVK2kdB2FA3bmWCPCvHaZqtN6nyVNrgLyLWGErilMACBdhaBGtCz/NU0WQY9HvPgazhbR/0gNpHqYLUM4xm9aaQns9e/YDjAL7sI4ps5+Saf7uJ0fB6Eq9XyJUGAeB5NPlfeI6Z9GtCbguHQoqDaHn949f7fRu/ejHiVurDWYkBqn8Wy56ykuOIMd2yDWi0+A7IBhAd6DfVw38QiPiwv6D05e4PrB2qfuxKLcxLGJMaFvg+o7wOl+IP3D+kquqskgtusrTkL0XKZLOU0vJtLbOvq3J30aAVPoJC1zIIEJFgpf8BCyn0P0vFtNFnPbMGFPui9nz8sBW3nI6amgNUbrN5g9QaOBY4FjgWOfSocC6L6o0G34KcHPz346cFPD3564GPgY+Bj4GMvfLz/KxeAjTuAjVvefQBkvAtk3HzLRWdxsc+NEkeGiptnsxUmbry35OCIDfzvIQECBgIGAgYC7hwCfpz7hICIO4aIW1zkA2S8a2Rcf5XTQSDkpmuSjhgp18/uxoi59rKuA0fOPpduAUEDQQNBA0F3AUHv/fI84OWnx8st77EDTN75/Vi26woP43os++WAx3w7lm0u22DhxusnDw8C+94nCeQL5AvkC+TbPeSLe2GPAvviclhcDtsGyuByWFwO2x4A43JYIGAgYCDgbiPgfdx3DMT79ARmvvcQA+nugMis5mbprhKa1V7qfFzEZjWz1wLR1twN3oWTcdb7vjcUD0BYQFhAWEDYjkDYyr3krS/sLt/TDijbISjrmiTA2T3B2cqAHwakrTT7uGFt0yy2gLaVqg48UNssKUC4QLhAuEC4HUO4laZ74ltVDui2u+i2OEXAtnvGtmq4DwvZqkYD17pncANU6wR/B4lpXTICRAtEC0QLRNsRRKtvh/OGsroAMGz3MGxpbgBe9wRe9TgfBmrVrT1uuOqYsxY4VdfQvZyCXO9bMe06BQMYFRgVGBUYtSMY9U04J/iRrNPv42g2Sb2haqkcEGv3EKt9igBc9wRcS8N9GPi11OjjhrH1M9gCzZYqOvCoa5OMANEC0QLRAtF25VLgFYnmZTReL9P4a/SjfIn/7cC20kC3HbwmuGaigHH3dV+wbdAP5OJgW9OP/AZhj9lsgXqt1XXw+jS74Wh3ubCXMAEYAxgDGAMYdwQYX9IYb4yLbYUBi7sHi2vmCah4T6jYNuaHAYptLT9uTOwxly0gsa227iFiu81oBYi9BAl4GHgYeBh4uCN4OLvJ5tV8sl3QuLEmIOXuIWXfSQNs3hNsbpyAw8DQjd04bkDddpZboOvGqrsHtT2MTivc3V74AMIBwgHCAcKfDISfnIxnpDbZPr5cXJYsBumFRFGjsbxT8sIigeqrdCCpx9Xtk7Ico/rRKJ7Hq9HIBd5bV21F1ZlIXNQvwpcmstoQM+f65XqVtEIjaVpUq4NPvh383D8pLrzqMWqF+q30fdZ5eiL7Xc7ACz2tQbqIxvE0Hiu4l16UvS9aT1uQMcvHK36UOSVK6Jo8BBLZaBXfRdkvwX8G5a/4P5NoVnZ8Cu6LMQksusKOvZ1Oo/HqotImqiWap+tlNLoNU1H7P6nS3v0trTv6mXwWhA4NPV7kch/26Tk4PAY5y9JhOJOTdWbH6Nr9MifU6mNZ/SwxDaUWqgEc9ordFjP5hjtMvzBtAP/8PzTug3ly3+sH/5KV7AsAka/hVUCqHjx3S0oJMQjYkRWzuYkFXRuouQ0Xi2g+6fEfxqNqHeVPT8rU5jya/pTm/BNKdBBKJKqq1yFzOqFCm6rQ+2j1avIbSQJ5Tf55okYhKNRBKJQ5ZfV6ZZlcqNem6kX+wjwNxyzuG2maozyU7iCUzjF79fpXP+VQxc1V8eFDkoUMlfvXQhEtpaGGB6KGlrlrUkL3dEMFd6OCb3+XQbftVLFUC1TyAFWyNIdtVNM+/VDRjVXUcsf7ptcli8JQyMNQSMvUNeihe7KhfjtSv71cVw4FPAAFtF6/XK+BzZeeQwV9NhX2cF8qVK6Tmww190KWNxt8b1uFinmo2D7vc4OqdVHVmu6qKqlbqxvhoHItVG7XF8xA3bqsbvYrNBzK5nFBDVTNQ9V2x3wP5eqicjkIv0ta5UOZD3XyUKd9kfRCubqoXPU0pCUda0HyC1XzSQZ7BPZAqF0n08M8DqeV88TaHhuFCnqo4P55iqCAXVRAD+qVkv61JTuC+nmo31PSIkAxO3mcp+UR7vJJn22IFqCyVpU9OXlR8y94tabpW8b/jJZpUPfgyQtabWfR13C+ClaJpn1Ypn8L4uXS+GI8i6M5ydbJSYZ8lOSV1ZM/ezWLw5Qk3nkKXlVykplxOf8s03X1/XuuUs7z9eapMqPAfzY0plUJS05yoWDDtQt+L6nJLfHsl2W/zq+k3af0HJsaBferoWZR96vA196UDiLnOiNVv2p0Q3pC/Eep1iAv8qmsF+eBRbg/n5+o07xe+lOuU5T0VRbL60X5N9GYjFwyryvbqusDXaP/GWxjmZcK61zkT+r5SWqadUkm91PJhuduOr3z3PGl46Qx/8v5EqqESOPn0hFRvEv9sB9aberGzfPohrnWdKk3tUexmjqVRtSwZ9crx6mlLvXP9yxdU1dXeT2jzk7mrjprPQjTrY76HMxqntOH0UpwhMh6KiQsz6antccnutvdpmM+rSc4UhV2f6a37brNmepUb31OjTTOLz09mlEto6WsZjR9lv205nx3uJeOMwjtp/P+mfa0EKnoFGSvzWhv9EAIGN1zcRlkfT4dq6SmdqlrzenRTd2bUg0j5l6lBfJZdrCU7djFzrlybf3nLnx+ndP5dF3qkzNxs6kz98+pM6WIeZf61JQD2NS1iS4/mj67vll3BzoVj/LaNW8Mt3Et1FRVzejuuXbUtnXUpV56JSc1dZJ5yLs9mTvpZuMuXqe2WlpnujRuJ2VRmnA+GR2ABu9+CF4EP/384e1FsBbk0lejq2CxjKbx74Jn+mo0iabhera6CtKE+dmZ8J0zFZLZLJ5ERiXiFoVw/qByWgLOaUkDqnMcBaGqMpqI+uOU676OJ5NoHlw/GJUk66W8O2AcLGbrm3ieDrJvdUsuth3ppnyJc9u0ymSDkU420KIxqFyB8NlvYzecEQAaxdNi/gt9OvzkUTpOR+FiMYoVmfhnI+mlwmYdT9WmaYGvn8RdbQqbHxc55iUb+j+YS/0tM5hXc3Wmp6/DOReWNNQPwXVCUqCJicVLzsb6j6z9wZLmJD0tZvGUc3Vk24a67SSLslazX2LyKt36e/nTHfVKMsXKTt2o31v1STZ3qJpNPRI1mh0qbPJUOmZur+yhfwXiQNnNQnvadrfYmWGpc9R984XmKDi3vSoj4th72sPguAgW5Tg5W9x2zNxdH9YMC42lo33FYbXvPFlG1bL9s5cxtbHl6RG1N7b9gDo6PXSPhxhOS9NqB7O8y9MwqqWtlr2Pbpn4zDHK5V5sPdyVYRl6DF1lAkqtL0yEfTumOvyWPZF9jLqN3UoNtr2lrYfY0eGhcyh4OC3Nqh9FuQvSNIwfK0/tZxwVSZFrIO/111uOpOr00D0e1bGUTSvAkuKORBWgmNsC+wAqBbYZBViKbWoNXUpdGlY6yXDGfK85IJZQf2VQKvH2PQxMlRtEDo6lfW0HyNbFobXjNFCVdtgHS8XWnUP1qvr9jgdKszqUhynMPt9wkHTXhpbuGgOk3m8Ojw5oV0blo+WLHQ1Hdg5fjsN9/mer7mdNH+a9oM7q2s1elsPBld6WYrJ76HT5fLTse7lhbceg0rFhta80JqWXF3wke5Cm6i3ZoiP7cJusR3WU/2Rva2tPytHloXMw2LuytcscSHuEszKOtjDjHobReixRjqK9oW0H0dHdoWscaAhtbSrEVXyih9WwS1MIbx8RmcazZSpY49Oj1rEcr2Eaeg4nR4KaelNqgA4d0jv0r+XjmFmPPA5TGKf2LkgDl+1uvbsU1x1Wbr2rT14pn1H5bDkPWl+0dEAm69Y3X+7D5U1ae1TT51hKIeBojBBfcFl3m606P3FWEnR5Ck/evSkmsXyRXWnIh+PygJaPSRaHZxymq57f+bZzXUXpLGQu5tGsZZ9lKLGpy6VLx7x7LESpVX915FsW7e9mEAsnMXY/hoUwXNNQ2q/EObQRteXX735gXaHOpjFuvIEIw20fblsUtHmwa++Y6ehQNxzZ3fvolqOg7UbZeY0IRluPti362TjItRdBHJrRqMu93/uAqzBpyxEvc/9DnDVMKwRSG+Ganc794GCbLWl992NbjcU2jW8NlzcktjSqOnDrO6bOK+2PfkSz2G/TUFbJeDGGagzLoeSmoXQSsR6aLXVkTu/BGbbG9Bq94nresYPz1+ryIXc/5taIddOQ17MuHtqI16Ug737Am4PYjUFEf9K9Q5sK78Rgj3lJI+tA6sDw9Wr09btwtrgNvxtEvA2Rihb8Ei3v4pRjwW+ieUxgQrGqvQi+T5ZeMeBBmSOxFPN1RuS3iLtX6RSrfD47CYsXpLFXyHKl4SluVPQH0e80fWU3olYWpRwWc7tNYarQ+/lPjwxXl2enFJ7ex+SoTRFHZnz1aqwK98/eZi7L4d3VxKXVrP8dzFwhgFueQJ974p9kHp08Mnubzko+bben1RWiH1SuQW4IyXdgsn34g/Y277U51V2XAdu+wWCbu+ifaP6byIb2OPvuDPBDmvzytsZgF7ehd0AY6viIHk8obOnpHZcO2zbMYIv7t59GFppYjPYnAu5E+oOaeLUdNNjm6ucuTL2F8OgR5z7P/O/25Bd3qwabXDb8NF6bkyVpf95b9fBCt+e2uls22PSm2yeZ43o2pb3Ns+P8xWHMtd7DG2x2weqTzrONe+kRZtk4QtLtOc52FQctr/R8klm1EjbtbTrNszHdnsXyvuZgswsln2RO60id9ja1tqM+HQ+gWveZBttcZ/g0IdVGrpj9xVbdBzm6PffWDd7BFtfoPcnMN9JE7W3i3Qeruj3vzfvMg11d5vYkEtGOQ2p/m5++x72eSFoaLv+6FGMRvNeXeTXdAPavYRoF4iqkSPBfiWvAouXLNJ5E/z9779bdOI6lC777V7AcD5a6lKrLzDoP7tHpcsYlK6YzM2JsZ/n0iRWLpiXIZgVNakjKTlV2/veDDYAULwAIiaREUjtXle2QSNz2BdgfPmxY7vPKI8/Epy2k40bnxWVSfnpZ2JSW8VFxXVjuhiWoKGnVqCy4bYHJQyJZ1FaABhcebR8WVvVzsCDfPTjzb3T5nVZhOXHszJ8sx/p/b6yH0F2AQB9gi4V+Y4VrH650m1p3hFoR7UNIByIW5dFILX4i1kM6apCA7Hmz2ljOHEK5iP1mgwkXAtIqklrh+CRc3LegBioKu5cMzb01ItPHqeX6vHyRtyxZfUZjbuT2P6N0yOACPxISf146qHflb7h7sbcP2+lDQidfnJA5F/j7H074RX9gL9vWr5msYvLCtsZw8TkMXqhOJQMEmpIdHD6u1MxoR2Luw9wgMZ+pdbEtiIrFJ3QY4yeH6dsDsZwHj8Cfi4AW5Lk+sRg6FrHTo+DvI/o50+hMOU46qJkbDIU1ZwgL48IIMlJQZNu069sEbso7Gvk76hsahXNPLmr8mtSVXv/IqmO11boHslyubXJHH39r6XqE+rloHror6g/1r757f/P2+uPn20/XkivBwGdmksBF6xV1BuNp+v24lP+PizqwngJvwawvYIry7C4WHnkF26QG+Eo1x/G34s8mAOSKQGsmkDiMumz2yWg6nY4vxts8fm8y73xP5s6aGviFva3mIjn+TNXJ8zbWKnRfAKOLn+jni4BW8UwcP1MILYB6mmdnA81aBVHkPtDX0lADXvQfo4n1sI55Iax865nON5lSPPcboa890rmHWciGmsSajsST80LV3gPd3lgBddghy1uYeVNkuMt0YTS+mBaOIG+/rDzjKyz1p/SNJGfjVszlGqvXF85q5blzNr/Y7uJSqeVX2+c+LrKXScFspX3zhj2Se4lZwbPj05k8lL2Ye0BY2E/8X9tSVp4zZ5OjzWc8WUHpM9PPyV9v2cOZBdaT4/vE0zUnSagY2YWHp/Zb/kGpcewuUXtOZzmiLzHzILuMNnoLf2YKCr4R36YD6NLYOKy6j7e4Esu/HU1v4d//EP/MnPcm7Apc+8Xx3IWTy7kvW2/yC3P/kT6cT4+7Sd8Vs8j0/Us64mzZqFTpS6V5ZC5kLL1VuLlXfD/Lq3xZ12f5f05KpTC9nqV/ya7yFXowy/0r/2BRTWfFD/KPFzRsVvh3/uGM8swyfxceyunALP/P/KMlNZiVPikulKm8Z+xndpFcWN8Xhbn1WNtIgU9NmaDCUMPlscb2GmrzdLBfS3FJ3rvmB27f9uotUtMEG7K7rrMUBGoTH6gLIRCTpK2ka1EDr/9AqBhC3hilT6G1SK7sTsJF+4YWfkecb9fp6rcYtEoXTakXEavU6SOJR5mblnkClST7oSrZyTUPEhTpTi5+Asax/1hcx1p0eeyyxeq9+OT+3zNL0u3SlDqcTbAWyY/Z6oAHG7CdENAFA4/C/uOiwJUuSk89Vvk2v7FuP737NHqK41V0+ac/PdJa1g/TefD8Jz5w3y3Iy5+eAz/4E+0XjUj/9H/99a//Y3xpOYsFrOFWQRiz2HFOl0bQ4oCuVMKsu8skTN6iHX7wyvvmeK/OJgKXtuFdFNFApgC+2ucLjIiHCkJ8Og9bph1zR0m/Sm/dTu9AnxZdLA1sl6wqWMpZC3fhX2wT2DhCh7lZwgoUlnpR7HqeRWjUsV6l0mMd+S6ZcnPvFSvki0Envogg9KQBywIiUiiCXW4f8PbAMOf7nbWnWfYfE5O5SSgOVzE+uUajylWReDCznJff/lt2BAVnkMGKdkuCHZJoRXWLVK1KKrJkl5OPp3ObsmTPjWKJi+VXuMM6io/OV3nZ1Al5AVVTsrDXKyqUuKKieL3yCPjDieqxhw0duq9fJfWNLyvywfNVMgBAYcz+MeKIlPWlShpfMx5HGs5lAa5UWrPkjwkfY75ymEgGZVb+aM/DG1y1+UeJgndJfytT/ogRQw3dWUN3LXqrnV8MpXIcM6hz2IKbQ/aLXhlFnpCPptEl05DJ5lgGctYIQ5Ubi/SJLlpN1Tl6tJND2kmFNLpvGXIyEbeJwndoDWgNfbSGBjhXYkEle6JfKys57wKXWJ1aYumEdLwZhXWRbb/yxdFbx/MA66Qt40mOy+wNYAhcqN+5mFjzgEGmfjy7DdckB1TJ3hvl6/jMLm0LvC/qOr5m5L9lTtk2YGzVZmloh1tlyyDYWSbFVN3AvHpOp9PsGCQUaH55+tleriUBBZUmkZxFF1SNWfrGmWTkYC9GUqMRjyzpTfE+nRzuL7qareH8/BwoaDkGCT9BI8DkLdVjSp9VZ2MpI/ms7xyfHo0zewNTXrIN2wDeaFx6D7KVSIpLi1zBlh7tDoOqpSV7QbCSFJwWnhaTdE3ycP6T8ZQJR9QzlkmPcyMqFMZd0Hk7iIk/39gO8K8K6cZNaYMFcecL4MfbLo2N5ctuVvW1MOHYAZspogw9KttkANz5XBLJN5UyD4zG2qkb3LysjpThxTyjdANx+4j9C/XV8v2t7EM/37y/nTTnfKjtfCbhMgifLce3zrNUq3OJqeUnonvo+IxdsxmIWfmSc+SCZzem08nEuudCv7+IhFnm93bgAgEnuYNnHZGFNVqKDSdg+AE1iFUyggl+TGta5gf+iYTiEgP69bTYs5KQ7JjOf1VDTOfNwHshTAFg2GzecD6Zl+yR92/CilflOTJ1SnkPUrLJHVyKwp2Uiyx4E4mzyJj+JO1txrh412d8eFWbl3xqsz8m9cfe5jKvS+rpTe6xJGaYnfmkXqb8uPB1mt3q8jtPmTvupRr09+C1oAmXcnlLJ2D5k44gxbLfimee2IU/9Gd+ZHUTeTOTucmEXndSl6dZs+VdKo/wRPpMYkwZu5AXJuQ+k9Cutq9Or368u/qvG3lVY37raionvRPiJXEz3qmRTD9mGZ2ZaPuTNkjRaO2wTSSLk9xHfwPhunPOd1bopK1Syp3sODM2Um5cRkgft39PVI5u/zXOIczAJOhMPfYX854U40xBnUlEkePOSXk0u/BpUmKMOH2QKftV3P7NqSELGZ2mJq1Goa8Sb8nkWRULykeBi0M5fMm9S/IRzHu6cgnTPHVjqvaDufl7W1SON246OFQbsqbEg6hLXQ/ECH0Ig2cWuY94l/jYSmoosORrc+RLFbyxfokIM71MTywxjLDefHa+0aXTOiTiNAJVKUkhITsfBXJ8IKB5sFikq9dlALetJxwhdmPVtLxkhAvsS16dLokUE1l+SGaFf080L4VkKWFFyd+AgzVxSvdyRL5UoOLfZ49J3Kvevucv3NM1vzjjRP8k8dxi+p4eJ5oqJuttDRKKV/Ifr0L3wJqHEzPGYpwoNJOfxNJW4yyc2NE8klGemaubUfjgfPK9TXruYQX+6V5kEGCCvGdUu6TxkXyMsi8oWjamTicXy38jG61zKjxb6ZdSvlVyOSs3Z91SxoltjzhRbAcljmL2P/U3WzbjJRsmWpgL5D3ysH58BF11/bm3XjCjrigkCF36huPxZZI1oqU9Eh8CLmDlsc9cv6IMztaLGHPvvgj63Fuvfwosp6qMJJzzoxgWArSkf66juOKl+4Kw7qfaF5ZJMC9cFa3k4reSf/39whr9RuOcUaHw8e/j80lFg/hpnleYsH1x4IWf3br//P7avvt0/Z8ffvx0d19RyoM4meP4G2sFLjUZTXCRdKryo4oCoqfy8ZkHAmdrHKBxzsH/BMuqVmy4Cw/FSqIsWf1o6ywgOxrKQsaTytlb+QD0Wf0tD8932lbSLAF0c3veO4xVYagCZJDH+LVX5IdHHttGHxXQx/FQyO1BEzL/ZvN20Nc8Wgxs8agjpL0gS+ENd8EepQs4vsKuRiBVlSeYJKtUh0S2iD7qEcgyCqlAURQWWel8RNXS77IQ4ZnKL0F34WyuGB55C1Ktmm3/rMQeMggD+pvW/I2QX7XbMfAWLbiJtZ8NrxjKuhMAp8OZaGmjToCKhU4eHTM8M1hFqHxQeirQf7SJYNnsje5WxmUH9G3871oOrqzQs/w/NaWvAtdPM5ZMtx/JTN0YxP2b7hByBqp6djYPBJKc2su1zzOgx68Q7cdBIm+SSFvrw420o/yMzL30GWPGGaaRGaZsT6qntvZSJfi36ZMtzGYmuH9uY/aLXgoyvB/3FlrcW0hwxR1SLvDR/yFczX8SL+dzdBTGMyP+LJYnH8r889OkddUvZvtCWyMrRNq6bA3q0jMljySD+MTgLLmPEd9N/85/yzWjcKA4mRR1qRv2R9U5qAT1yG2RfTd9y/76+E6zRtu/0QpkKfGe2eIyn2mRbIAI7rcPJygZg7FV2wM5PO2eDQzLtCV2WYjivQQUB51hmdsWfwrJHNLj0FAdDFHx3hZGjOYBs7KKUUien1Vuo03LLylfKeyY5QaBL9WVWHv10ixnLX+cJaYxpeuqR+ox7OQ7mRkVdwkqXNJ6TdX0l18+vvva9HZWrf29psy0vP/EcgX4CzAulnQsl4UsnFZuT+31frJ7VUbNpJtXe7aR720lfzSwv1Xemdq1ZfKNK9Ws5fibUfzlz1/lQXxiBR/fvaff3b7/+e1/2f/5/r/sv7+/evf+mm0hxZCcLhmAsXqS44uNfzjeumqpwXdc3gVs5gT3ePHbri37/WJrzHTZEUKIe67eL1COjmZPz2A6/+OsYitutGu/4PbJ8v6SZr9D0TXmZ6RciHVEkoWnBmnhjZxVrhqmyzB4LjjQVFfUrW6YuTDRiQq8zEXOpC4qt4+4depW7DwI0WEizEx5hcl7apV6Y7FoCFTydbszx7bpVpxyzDI+UvVM/N4f1GVpaoGcngEvyH4gS0jumtIYLjLXrkGOv9H4Itlw1JToLsVqn74C5gMuw7EyRSXkCJZPlvbu4kVXXNL1bK9Jrrj4ieebWQSQj4ZvpwZn2j3TgKpYvk0rJ4zdubuCt0fOo+P6YygTdpYNihSIXKFljLbNjxGp9z+3c76drtaqvIg5s4kH8XTgbEk9+kq2QEmirdrHx7t6pKLDzfTfyOlmiBgeyRC+t+VMk9EfW3+YWX/WlpQ8uvU8xSQ5ryGNF4i4RPd7OD7HprbR2Kjc6WeHzkmw23sTh9S49O2tKpJhOrshItuOrdz5N49MvcBZROn5uukLdEYjKiGuLSrEcsmCmNwIqBgOEFQEUKvfpNs+zxGRDFA1Hl9W6iRfVsAMYLCq2K4u2CHBhRg8ljgK+nDxW3LKkKWstkV2WbqagHnMuhDzg3VuWIvQXFo8+XVF5sCMEfVohwQ8mxOXh+P3i3/nPh+QFMg8+EgLNGvLOTijCyjsgkeJUARvlOUs4aYsWjB4eR4XUnfI6/yP6uIrtEQ4Q16c+lGOT6vXJQVPVpyLzsz9lp6KI62cJ29cuNHKianKh/oiDMhluUVApi9V/m2nMXotXBHXxPDkhyhHfN3lxb3HNktge8dSwIk1kZiVYfkC7Kdvrs+4YEk+ST6TwOKjkAJZXQkflohn63sFLwNkQ0ZoAqHeWwlNYUnLm1YWmGa2rFCJFLDfasUs87f+RaZPBe7QJJ8MVdyMZ+Ba30CafNfxaJvZWobzFLf5pCFnNEzZceKLpiYawAtcpKzHfGOnaZW3gZgajfzbAua+Z9d3I7pu08T8OziuZNdk29TdSFrqyTrlegoL5WfOM3UZlCTachvwlmRenlg7N6sTM/neszmfa6/3m8qp/Z7vUEvT07l53ecLd8Fm7TTFJiBB8yAMYQ7nU/t/mBVnovjUK++ytVJMXEFVPMEL4bvqCsXaHR7OLvgnlpkOnN9w5qrIlcoJrLw0xikT14LSz1Ks/f68CQ/Bo9cEplieJ+eVfoO6p5lvf8/jdudGVpk/IcI41abBkKyBf5xZ/CRyjnzDC744t/4oqe+P1vlF9UARr9BYY7Bst6bSYmfQzgIKBtUZyEq6/hCMCnA8dimdNjAGw42ZCnrBI2QE578mRq9kgbw0o7jpMqwwYrPM32Yvl9kds/JHZkVp7/FRvpRh0yj2+vc0SgFkAQDEDohkEiKLGzKM138TseDhpYmIiTNUNRhQFl5i69GI9nCxhmNNzFX+wdQfApaRbrywV8eA1P+5egyE/KTYqTxVsZma88WK+cz8xvrMzujwNbO7zCwln5wIBlWsHv9gXGTh5AznPuTXlX9oamFZZ4FZDYaV/ahuF9NwN1oFOs12hLKMW83AolkeT1qsn1dRsvxqqjcGpi/AUEnEAwnbVx4V40iYhtF6XQpeAI0ulwyCn/uvzoAg+CaF1XD+DEgOwctlMJrmkj6oD3rPqhidnKWq4KfKabTyIzgTVZKKZIS2p35ObYg+3r6/vrr9+OnnSUUijyvJyd/z8/O/Ew+OcPGHALhYsRvC2GEKEgNix3bA2Ff8dMY9R/bYTFW6L88NM/gFPycJL27Dvnt2Pv7IeUR2yu7R0cwcOT52bYXdSWm3iqvGmKp0V8WRV6bHyo8+HhCpR99thN06WBXsxukqflqt8gCC4tx8YZYU2fMKV//tNufxKWTP2W7POyOSEwvOw5z+n87czjzOHGzInDfgr6muPTLyAXI6heENupX3FBTvzTW82CBzGxSDLX8O4o/JjbBkwQBM46Fl/9x5ZNlbdQa23tXE+oPQO4yreL75YZVc7mA+utmXO6i9+asEjMdadgNBk0N+u92rqjX6inLqCCJT5OlIY3MbpFeHi17vIQtJKcfzO0ZZ69m4VzzZ3ki//5Uf3mtmxAul4cjrbif5QOL50+4DLimkgzOrrJlld3O8wc9dDbP36N8VmCuHnnM7qeY/kPjuKfAIa/TuS8Xs211cMmbbt+vSMZs2sP5Af3Bc786Nn97/OicsMNx5sEsloMeWjvAVZ8rtPb7ifRzd3Ogm4MDOw5q8WMvxquC6PcZMafRJJW2smOU3OpkPYuH9DgaOhRYedfmguzVoh0hdVkoXQ3b51TTm0aLuapsmxQJesbZUZIV0cOUha+YOMpG/3rxI0mDwyl80YzWVJXYVa6ls+C6QbnVZO8jy7Izv14qu3dBYxiMxIFgceR9JwPyxOJz7N+pvVySMN2fJ1gAbp+LOgOmuwEh9tflZTej/jXXLcpNCUr9XJ1xEFlArnNh98Ii1WIdpzmbiO8/wD06eYtmg0xzQb5KDfzzP6UVeVy8maT4Dn7zS8hc8h7R4dREQRh1yEwkwFjrVM9engociYTcpbS07LsCqp4/lKxL00KSlbgSNFXT+ra0cewsj+V61Y1H8vqiyb6x3W7E8u48iaQKnQn92ornjvaWadAEjdxH5dKTsOft3IVXVGysZJ9/6vKFf+almRRN+LsDzWCW5Ul7o19nMDixHLB1Xh5HKqaBBxkBchHwwtAB2BhUoe5zcDIn8H0F+ogeZcrhiqLUR2BERnO+EFDeM2Q5n3ss3hLyxIA1G6C4IZwvmBkU03/oO1Ic1MHl4q5M5lYZ62HP8wGiqiqW9WbYvNy8ol3IzM8prR0ZDJmWTPqSJkl+BFgep22vY6dba5i1bm3kC38YMsNkdwtNzwEfe6Uy+V2xsFr5G79sj7/uY16wTdb5N2Ohjn220Fa7B6fnpbnAm0u+1m/Lyp9B598h5R4TqTVnfTn4FrRiXDi2kmzDNtslKp+e+u0m6Sr5XtE6tPsoX0Mn3yMlnsl/Y6PDlDt9gjAZquu1yJE9xCugU13OrD5Jm6dRH+jj6/V75/Q1cazFPpCjPS4pgzV5mXj24w7L0wxC8T3266AxRXa4dheaZKlXpNZxG+jyNECFOnE/anE/UozxsX9DqeZYTnF86dS4n1QmjYzj6p3ES6dMkQkVoe1SGtsgkaC/zmohTx/5TR9XYDsnK2z1xd/Lzw7FPDiqUgRdqrDvJ4zhF9HqKkCVgP+1disoh6tAOdTsm3M454BMkhHbjPHPKKtMfX1Y8hv69T0RREtuvIDyeUBaX/k1QRlVj2m87bi8Hwek5+g7lUki+LzVJrSiSR9Hp98jpL6n8bLiGwCZl/UPHv7dVa8d1GHbdVpqU050Cjp7upSh90aBqNUkfROffS+fvFDUPXX8Drt8Znj03nr3pVLz931jiDGmiknJaqrkXNZ2VKpHwNrWUSgfUyafQmXfTmVN1mb6WlEjpwgfkrzVW9doXq2orpdvpraM7k5ou+b4yE53yQXS9PVpHLxLp2cuC4p38jqh6aDq0E9qcmbabMPIE0y10K/Hl9nujpHwVj6OP71MmBpAhVSkhRPu5qIuYk6FqhLqUnaEVA241L+3pOf9u5ddNvjdLp6t/Gj1/jzw/XAuJjr8VC68a2iHZ+OEyZJ9g+uKOZ/pOs6funth7h1dxVulTUuT0ICl9z8boojJn8m7jdUJmrkvXv0/2+5O62faNdRc6K+54mBfjTmhBXogHtxVcRIm+U+fnWPfRyvHvUx13s26Azk1gCWRhrdkt9G4cWcu1522++//XjucuXfqNcJ/g9bbOAbgCkjGEwmg5U6hScvUxDJkNBc2W5zLZji5+E1KY8mfdxe8X43PJ9fW0/KSg39TNSDvBLn9mL/CrG34XgzuSFe7BQM7Upd7CiP0ID03f/nJz++mn99flQlZs1OxoRea0BfPZbbjOaEvhVmloHSwqmWpYs0THchrzgU6Bn+H2n5F4bqy5mDqvOrcBf7HUyIxvfytJeG90i7fEmUu7Jblzu3Dj9T5Z10/n4mW0+gasnutIp40+qy6VNs+VhL4su2eeWvUP5UTqjRr1pNKq1T4qp+eJi+IeKenYuE6i7xO/NRz9RQP+Iqc4nXYbEh3aacUgUyaTdYPctDq8etCnl8bL7tGJNO1EVIrUaX+iTw68k2upSBts4mUqbbHTDkedyjjnbjqV47eFW5TRmTTiTGRq0nFXok4eWzvCqTCbTkU82rS4dSMgk1S4SnfTmRyx6Hb64HaK6tIj9yNPMdqwG1KaU4fdkSKJam23pE6cmvVGncooqgyWzJIPomc6qGeSqU63HZJai+r7Ia0hdcv9aHJzNux1cvk41W7n2IkqcfHTCxcj1KRPPiaXKHE38EaXQtEIutHbWJf3mSVJHbP7zd3IdqjeR9anTas6iYA+pNmd55y2dHsHWqI49Xei5dbSrR1pWQbBuksRVdbAjCfpUDo9XIJ0032UVaTTLkSVta22G9GYSqdciTIXXVPuJJ9/TuJMjp6YDV1Jt11JoiC9cCT5LGCNuZErWQ65zjmRQmazui6kkM0s4zvKWb32gEAqExCZOwZljKLL94UuoraLSPWg076hkMBqJ1ijqEAmSMadNF2ZkbfY0SXUzKKVsejOpJdSmnJlIhtcHRzS9IsK02kPINednRyBIj2SiT9Q2laHMU3dGewsYb5bOYzU7FWzk4q7vo+Lija49FKd6japXqNeu7HrdXpmRLPXG2SHPY4mPVDG4XQrb47SX5gl2djxdfQ2LXgbqUJ12tlodKs23qE3r06BHjobqYt8mGajyaYT6HiaFnX2gN0TOtQpC51YG0kKKpWv2/kLDFVwt9QGprpolPXA3LqPscQ6O2O54rdnNHkyoJH49/dORJLPqETY67bwG0L8oqUvTsi8H/z9Dyf8ktYkHqMNA834xLaqHO9Lzut8ZU9/pXLVFrodqgs68C8sQ5Ezn9NxBONnzWJZjogzf2I+YWK5UzKdgF8IifXsbFhynm0pz2svdlceYSnXSBhZ5FcqHZGfx6dyCokfe/StdcwLfXYfn2LryXnJFeNYC3e5JPAwdTPQjPuLrXhEcqfZz4EvhJZOJ1c+9U30BX9OrGAp3FdIdWNhcbGkvWGlcr9jJ69El7TeefyF6tekKEAYy99+5/WwWSZ5iRn+xEr8yiX9K8zYWlp29twvL3K6rbj0OH06/RKuzBwl5W81zl1un6b+FkYjb+KZspjl2DYbA9sejaXPTe1nd7HwyKsTbt/ZflTu0pekUV8zzS0mo0o/5zcprEKYSuJNOpD8xkrmPfO5UMEm8lOrbAi5HGGEciPDn5cOC09kdL32IW0Xy2BU9hjnQuuspLlQVOBTzQ0J9dWOH7OZis+DSWPuxfR4rlg4iQFhJYvR4K2PSByLfGH5EZlA8jJbtqwYD2toeFPfBqsNTCyjtNfj/XJLnWBqwrZSaJWzjilyYhW/xzSBfUoTKEklNfRLfTJJ/zpvPA1cd5/JwHWC19y3lGisfPG1PHNY4Wv0jX26sL6ckOt0XONjtw2ngYtwygmFTvD+m3aTrZXvxdAmPpI/hT6zT9fYEKoZ8pQ/p+M7FYPQbbOq71H12dpOz7keOCldSSv0acEkClKR/AtdcC9ccLyVoo3umNqhwYD01hKb8NrqlHen6LMPk9lPoiLqxGtSBdGkJ0NH3RNHvbFjpiri5pG5LAXVKfnpqvHom/k17Z3lmQJP3Uu3nxCxQl3keeoq1UaRxQ29dz+9NxHiRDduPDB9N9AG/Ls65eIJuvXDZJYsK4tRqkj90+i7++S7qQhtj8rQDrkQ7WU5+eIJeeyq4eiX6TXulXMpKU/eLbeWebNKOXKJEau1I5/+ED1zTz3zqyQJ5Sm75teem18DjDZJrs8TZLa1nNK0TNTR5yhVPIbet0+MNxLbryA8TsI/We6bahi6blz1fasqA+rp+ddDJHotqYEqF6dEFZRZK9HX9sLXLqn8bDgwZRN5ftTT8bfaoeiLsTXne/PpYk/X87aXFVepCvnUpRpFKKT5RJ/bM5/ryJLJnqLHdfpoZPV9bSGv7qk42b+xRAAZV7NViXLG1LkXNZ1OOJFwIR2sRAd0WYPRw3bRw1J1mb5K0+4O3a9qrOq1L1ZV36XK8xuf3vK1/TTOJcFX5mVWPojOtUfL10UiPXspyWJ8OqtX9Tj0wcQaOLqsSYd4gmeYD5T/unzq0ixTY8Xj6IH7dLwZZEiVRgjRfpZlHjyhg85Vw9E346vvmzUptE/PNR8oU3hJOcxSf+ufRr/cI78MWUfRLSdmVzUa/TK8+j7ZNJX4CWaPPFbG9HKCvN1ToO/wKjrzPuWkTE+O0fdsXHLnU1buNjiDslrNTLBXtuDs1RFtZQKtfTWEInFo5QuSSx6IFT0Fa2/B0647Ph8AlyqqE31jRho/raOkt9aKhGUbemN5JL5gDy3d8JkZBC0nWj8zXgw4MuGYonVY8gf3di4J9f3WDdAiSBhrc1knb6XvKB6Okqzp2zTTcbjJJ7xu7MqLmtdeSNO1pxnmi3dX5NO373VlRrPXZtS8OiPpKFyfwQ1QVUkj92RU35UhuS9Dd2dG1jYlF2OUyincjpGzVOUVGNtrMNJ8/W8lWZuN77wwuAGofMNF/pOl61OjKZiUxhrBasd7ZSzOuOi2UvnW9dCKBKZVz6N/Rv/cI//Mra9X7jlrmLt755yZ7uKcfyinjR6Ob5Yk9sxeRdtuOuHaN9Bqc+8ZvoZ+G/12j/x2ziR75b4l1rq7F5fZ7i7OXO7RhuXT9XmbM+79wAmN0d2ju0d3v5u7V5lorzy/Pl3y7pNARTblXeaDShc4tKlBnRw6NzEcJmuy4YzwGASPHpmuQKoP6+WUUKe6Yb79PfyVmQQqnkS3j26/J25fZoA9c/rqDMz7uHxNgubdHL7WtQ3Z3cuzTSvdfvtpmNH9o/tH91/p/ouG2ONpQJ64ue50oMjrvP+0oHR9A5se1Mmqs7PCYbI410WHzDLP4gyBM8QgZgiZUfZrYlDb6x7zgSaR9E7TgNbXDdr755Jiq91/a9miMRhAV4+uvtrVCwPss6/PZZ6u7ezzialrePs7SWbyAbEwJVm2s2zMltNP12Zl6hPq6tmZJERvj96+H7zMnB32i58pMdE9eJqylNg78TXlnmxY3lyV1zvj0Q+R8BoX7ejG0Y1L3HjZ+HrlylWptHd358pM27u4dI0rG6Zbz6cMlzj19nJpo0tHl44uXePSE9PrpUPP5+re350XUnnv48yvZCnbh+PKCxnJMz68nJl7DxC9MomwuYNWYie6nN0NOacajmkfp7SXQ2rOGTXjiFL9kVXRiPfRe56C11F4nELy6ipXk3czRc1T+peCb7mT5is3cigVziTvSMY1s2hnvEH76aXrQq+VqXJxhYcrvCGs8Iqm2KsVntxKd1/hKfJd77LCU7q0gZ2d16QezB6iP1A+69rHK83yfe36Ph64xDmgT+frpdbar4P2GkPe48S9zqx3Onqv94PDmhs0acMzU8OB8mnXnRnMsgDv+DrOCzgv9GhekJpqr6YFjRXvPivobHqXSUHvAYc1J5imLc+msT1WPu/aaW53TyRcpyycTHAy6VNy3Eqz7lfeXENj3yOlrqnp75Rt19yp9mQCOjt7o/nPeuu5xKdGqnvo7I11C3cnONQFpI7huyXTKou+HW5WgQuFwI0Djr+xrpnysQ5P6T+oYjp+zLLnB/ETLW0uKgVPm96hYI1enwLqNtgFF/RZ2t8Fz83vPj7F6XPWg0MfgaKjCXWW1ivxPFok/StYxoT6XcIS8Isa6PvP1Je8kGg8pSNhXcWxM38Cl09+XXnuHKpykysS/kVHDGo+9x0q8HPrfkHHEr65t4IHyP4TTa0r2bdJen8+ndBq0uKm1s2a1idet5yQNd0FV7uhWkdFt6JaTZ0ibX9I6N8R8dkNAl5An2HlTKyHNVwWAPPVA2HzDR2kBa0FhjspOffyL7dvp1Rk1Bk/EQ9mr+XaZ3O5tXAj5/nBfVzTtkcwRyXDQJvjsLFJbkRgDch2BUamPCJ8HuC3Jjge3EazSWfV/BDz4fi4ZKWXCjpjc0dSAnwDz39HzTMk7HaNKIZLJWjvX2B65CoSrENrvo7i4Nm6f0cLvKWvAX0Afv9vmFa5Cp7Beon4MA/bT05kJ6VzW/43bopwh0q6JAIZUY/5iU3ljvdFfJw0Ov3D+m+r+BX8WBAvdr5SJwg2ODljSxh9ycJdsxJkPdFWxF2Cu6QjmM6Y0J2JpWp3xn8Lp2rYjilcm5IWw2rhHkoUAx9QlyPckv0L1UfvLVV258Ejt1QWdEzyAwEf/sOhE63ylQvqxNily6mzo+/RtVfg804kvu9SUvKV51LDmpXeTN45KxR9KW6X2KXMtCi2BkjbtkNr+Kvvl0swKIMXv6ceMPX44jVextWaztyh+y+jlm8fFp3m63r1e1UHaXgxuUz5exWXKyFXpljL1ymUF8Gbms0avX/Hsw3NJ3yvUWS2mZLEeHsVLSlHUn6NtssK4l3Qp/lrtDcVGQAb75g6lZWuqgpehK7s6n5UFS4pXZ59pdkeKHKx1O+JOl3AXtLWlKepr53O5M7D1haH7nRs7ZbLznjt5wIlBclqqOtlkxlLdaKh7nArzzfUHmo5Zbep9hYIvLVbW6D71W1miXq6jwIUC+EtlRNl9qpAXpS8lobGWYev7DftaQrU1VhnptWVyLup2azYq0pNeZr6avRRV6BYQxuiZvuthA0LN21JnUW5ael8WGwOb22BU9veBpRZxBPQIb4xAc34GSBWKb57LlBGHgTyEOHWib5tw+Pz8/PrBFqJ4PbM+RNZrD2y4HsFIZ9JGRSTvZ2Tw3BwfyGH/vn2AP2fH8S0lHlAzT92aVz/QOYOYF6vhIND4YYWt4XrA454bBhoEpFnh0bH8ygpkvBGZICTpD2jIMwQ2z3PigLYkyDjabZnW4j1b2wECjee8vuF49AlxazXcy+ayC7l1O4piWXfFsrIPETE0nBaWCPma/m3/D+h87a72Fb6ENsvf3G81ZPzlyl8GfHlHP3r40LJURfIBe1Sss0wSUqeid8ZLJptvdmu78a2nR+T/CZb7wYFMCqAq4rbQ+/IivgL0CmqQPxmWt5iMDILdi7gLlhAItcx+9NJ4F9nBfAfu213XCj0FdDkDbwFv8AmvvnBKys+85b18R0DDOnTHGBkD7kgH4CZ8kUyVLEwUNNHaoWvzuZeXK0LJv8MVufG+Z2nN4XC+G3LLu/wch3DDh5tBfl1xe7kDaxovVrRRZI1D4Mo+i7bZoB2owl9t1CksMUnd/5kzRmEnd1mY+OQwWJX4I9gx80vDIi01CcSFrbS+P5Z5tWsSugxyK0Dvdq+/nGRwJn5Hbsc5piaT7W+SzaQZE2mdSb7b/kvJJ2dPzm+Tzyb+kg6cYSZVwvfSN4VRgNTFf8r4xnpmosKSKw9ExcgHhvB61l4V2ttUr+Ta0DRz7DdKepoitUICf5AfBI6dN78woBmDjdvb93NIV5f87VT738FhfNNGzaN8D0XN3pi+zK8eRHbwQ1FGVOYM3K7ZykdgTWUFsV6Mtrv2trUb3J5pdvABfnBJnj6WRzwNYF8X85saZATwXS7xBhPdi/0miyl5YVkOZadHJKcKFs/ZBY1Un2yH8PVnClVdEMfH4nBkJRW2u9Pxxg2+2VrJ6g/mv7iO+Hmms39CwDjNdue9NsZVzzgNWTeuaffUX/IhL0lGFB9guFRlgf123whMoO/p3dUs9SbqvxJvu1+Do+eq58VW68zva1CIWIFPErWATmJjrWtcRZO7Eh24Z8Y/zKa/p3/Vg/olphAdWbWoLLlDDfnTWcy36suYDylVgcqaCf9HWmqcziawNqd786Udmcqvp7ebKKYPAvoQbU7Lv0453rsxFdR5eZ7+6B1pfcIg2Qsw+bA7iyBy8fltkRnQfbtlF37PkutilkpCGodvaXfTH/+dGt/+PTLz+8u1SrKrj03bJZeh2RazprJ1fwXH1ZT/i1z12pRW7Dhxyf+M2WDy8Pryfw6t0EuHpvKiw9pxaqEIx92gnzYjs9xjyt/I12SpEKJePn0mQ+OFyma7y4V6jMtNXR6B2u3Tz4JlqPz0rfnYxB8+vm5RsTFV2kLjduQfCItXT3qhQEBQk877WM/5UMtiG3l4kVUrJSk6sVpOoGPrT/QsT8/02qc+ebgaKxUFrXJQRfSIeYLKH1701F89/7m7fXHz7efrqdAlWNzmdz/dcFvfPRfHM9dXIWP62fix6OKieaZ4zgz7UPLc7YAZTy+X375+M5K6HPrNZ3T4JPRw4YKLz8PszmbPTL+3TqvqODJAfQm1YVgyePXi990Yvr9oqLcc6Dm8KiQ8WZYkYZadvHvVYUDILQJ1sz6RADu8KV6sBSheBhCQMoXQf+hWfpU+nEWydmaSa44lW95BKJfQrnOlG+/sT76CTbwP2fWn6f/95+nf82G1bRH3HyAKQZAwr2Avbfz6L164eguJSb3MRrl5xFYtUSsKAE3w58ZE9TYWLIwW0fbhbOuVM20KvWzdEpeOfNvI15QxcvM3rPy4Mwc/m5ahJEs/p9UFGJPBPDFMHgFlVuQuUfVcMEFE1GxALlrYa2CIPQ2/64pPwVtHPcZBEqe1x5jPMeiFJf2mLZiAStOAZLmgZ4snloun+pcRA1CAK98KKbdWVfp/KJCLvrpW6kuyRdjzas53mzOC2V5t0k5MpiiEN9Pt9jEOEv72ZPElHu5DMknclHLTzwxTghcjFAlFi/5pvzi0+XllzNlQJ8r9gdq2KyYieEL3KQKr3zdtumn97d///TO/nz96fbT9798sN9fX3+6tm//6/P7m0vLc6P4C9iyau0rJtOp2Bz5CgvgL7JqGiw/bwya9lt/NB3U689v93rx+v33n2gIlXn1TGJSSVjxPr8U5SdtPouudkg30nYLKCOVhuiHpOGZzkLIeakIOLNFM4EqY60oDr/ut8chGrn7OBW2LUxamBJqCzsUAVt8R0TsstH16ZowJiogwHx/kZ1F8a0gXBBYXhRKYLODYEzT/wW+twEi+oIztBntvlxeoQy2vhJ95psA0/JAcfCm2MkbQJv8OeG2KZG3xBArjXEHA8wf7VBulEXrFVwuME1VozBT8MW5EGQSmkueSIJKHivKSpDYQfr8mQkUy0NG9g8BkOVLm2TFUegGB3F4Wx4zCzv43GaLLPautNxCUXRJykoT57XKk/sb66d1FPPFrliNJaduYHMsXX2JI1h83i/j5bzFCtTp6nv66ft3MkmIF+GXXpT5f9NuFT7YRvBsFZNYc9UuynYg2YYBd8qaXZKCBsgLLYhkW7zEsDR1SbWwqm4YydJmTUEgmjrzgpBXIYZWtSWUc5ja7hUlpGIAZOMK2PcXMdClSQhU8CCJJdNi+JKZ21O5hAWJHdeL5Pn21lF5aQ0lyvzg5Eyz8M7oNw8DMwruEX+U/3Rs/U/rz1y9y54tgYCzpnCpOsAGVAPhhhJ4RPzO+aWZqlOFbhiPKtdOWWgoILYyHifZFx89EP9pfGk5XsTYKbDpH1qPJI6To0MMHgAUK2LKUyjjXgyrkPE9A8tcf+6tF7wAOFfqW/diSO4heHx2vpFCMQvysH58ZCfQnMilMcTZ2U5DPTZVfTYHwNQCv7lLYWaQ+yi/BIPJ9soNrsXCR004kepxVoblunP/kgSZSTdzzyWDXYxKTQbBBXPk81C2+4Vu6yMJ5qjo9OZJRyKDz2dO4yAPC3lYyMNCHhbysJCH1WseVu5EX4doWPmzisjCQhYWsrCQhYUsLGRhIQsLWVhHYGHlFiRIwkISVhskrJySDYeDxX4jBQspWEjB6j4FK+eDGmFgFcFzZEwhYwoZU8iYQsYUMqaQMYWMKWRMIWMKGVPImELG1DAZU9kEpUicQuIUEqeQOIXEKSRO9Zo4Jcu63SH+lDS7ONKokEaFNCqkUSGNCmlUSKNCGtURaFSydQmyqZBN1QabSqZrwyFVZXuH3CrkViG3qvvcKplHaizJVbbwPVNdSYpQAflI4kISF5K4kMSFJC4kcSGJC0lcSOJCEheSuJDEhSSuYZK4FDdXI58L+VzI50I+F/K5kM/Vaz6XYn5DahdSu5DahdQupHYhtQupXUjtQmoXUruQ2oXUrlapXYpYBFleyPJCllf3WV4VUELTObX03gIJWkjQQoIWErSQoIUELSRoIUELCVpI0EKCFhK0kKA1OILW5jZ4m6y1BHMA6VlIz0J6FtKzkJ6F9Kye07Mks9vxyFli2ySZuqfkeRXzLfX38BfSsZCOhXQspGMhHQvpWEjHQjpWi3SsipUIErCQgFWDgFWhXUOiXEniCyRcIeEKCVd9IFxpwIHm6VZqT4FkKyRbIdkKyVZItkKyFZKtkGyFZCskWyHZCslWSLYaNNmqwNRA0hWSrpB0haQrJF0h6WpApKuCaSD5CslXSL5C8hWSr5B8heQrJF8h+QrJV0i+QvJVbfJVIc5AEhaSsJCE1TcSlgIsaJeMJfccSMpCUhaSspCUhaQsJGUhKQtJWUjKQlIWkrKQlIWkrKGRskgU/xj4j9ecwvSBxPMn5GIhFwu5WMjFQi4WcrH6zcWSTG5IwUIKFlKwkIKFFCykYCEFCylYSMFCChZSsJCCtQ8FSxJeIPMKmVfIvOoB80oDDTROuFL7CeRZIc8KeVbIs0KeFfKskGeFPCvkWSHPCnlWyLNCntWweVZ3oQtBKBKtkGiFRCskWiHRColWAyJa8dkNmVbItEKmFTKtkGmFTCtkWiHTCplWyLRCphUyreozrXh8gVQrpFoh1ap3VKs8ONAI1wqek9byfrmkhl5iJ4DfvfJcJ9q6mO+diNyQ8MWdq9yNKKsS1EdmFzK7kNmFzC5kdiGzC5ldyOxCZhcyu5DZhcwuZHYNk9n1A4nvngKP8B1eZHQhowsZXcjoQkYXMrr6zOjKzWrHY3LFJKJyF7DAI28bGxTRTqRyIZULqVxI5UIqF1K5kMqFVK4WqVxVSxHkciGXqwaXq0q9hkPmyoUWSOJCEheSuLpP4pLiAU0nypJ5BuRRIY8KeVTIo0IeFfKokEeFPCrkUSGPCnlUyKNCHtXAeFQfaFvv3PjpPdtdof4MuVTIpUIuFXKpkEuFXKpec6lKMxtmxkI6FdKpkE6FdCqkUyGdCulUmBkLM2MhmwozY+1BpirFFkioQkIVEqq6T6hSggJNk6pUHgKJVUisQmIVEquQWIXEKiRWIbEKiVVIrEJiFRKrkFg1UGKViOqQVoW0KqRVIa0KaVVIqxoErUrMa0iqQlIVkqqQVIWkKiRVIakKSVVIqkJSFZKqkFRVg1Ql1AopVUipQkpVfyhVBUCgLUJV3juY0any/Blj3owyOSArARrzD6BpSElSxpVk2jQZIqNrh4FEEliLJLCdlRmZY8bMsaxf+W/kkSGPDHlkyCNDHhnyyJBHhjwy5JEhj8yAR5bu9sjwW9gEyOeqz6/aL5T2VcLkVXy1OwHWIFENiWpIVEOiGhLVkKjWa6JaMqF18BrFYtOQq4ZcNeSqIVcNuWrIVUOuGnLVWuSqGa9JkLWGrLU2LlYs6tlw+GtJz5C4hsQ1JK51n7hW9ERNM9YK/gCpakhVQ6oaUtWQqoZUNaSqIVUNqWpIVUOqGlLVkKqGVDWkqu1CVXvn+I8kDNbRB5d4iwgZa8hYQ8YaMtaQsYaMtV4z1grzGqZWQ7oa0tWQroZ0NaSrIV0N6WqYWg1TqyFJDVOr7UFNK0QWyFBDhhoy1LrPUFMAAo0Q1eC5Qvnvl0tq3CWeA3jZK891oq1D+d6JyA0JX9x52bmIUjSAPV6FiVdh4lWYeBUm8sKQF4a8MOSFIS8MeWHIC0NeGPLChnkV5k0chOSazNdh5L4QUQaytpC1hawtZG0hawtZW71mbUlntw4mHdO2EyldSOlCShdSupDShZQupHQhpatFStd+CxRkeiHTq410ZFqlGw4BTNpNpIEhDQxpYN2ngWl9VGNkMGkte1LCdGVV7gwgPQzpYUgPQ3oY0sOQHob0MKSHIT0M6WFID0N6GNLDhkkPuybOAtlhyA5Ddhiyw5AdhuywQbHDZJNbB8lhumYiNwy5YcgNQ24YcsOQG4bcMOSGHYMbplufIDUMqWFtUMN0OjccZpisl0gMQ2IYEsO6TwzTeaimb7PU+AlkaiFTC5layNRCphYytZCphUwtZGohUwuZWsjUQqbWwJhab5Nl1pW/wKReSNtC2hbStpC2hbSt4dG2Kme6DnK4jNuMhC4kdCGhCwldSOhCQhcSupDQdQxCl/FiBdldyO5qg91lrIDDoXpVdhl5X8j7Qt5X93lfxr6raRKYqQdBRhgywpARhowwZIQhIwwZYcgIQ0YYMsKQEYaMMGSEDYIRlokI74jz7ZosSQjLosv9VqZvrDtYsuXJGslUPKF10+IjUC6Hb9MxbFIQTLIvPdI41LceNlmqTX4ObpTUke8E3wfMkoekG4gfF9rF9QOh0qNeJfhG/N1X2JHIv618U5Kru1xScTEp55ZUckrSjVHppnd+T5UjX24JtkmQS9vecgQYJG/bRXtKxr9oNuWGUS/4vApiqrCbhOCwgyZk3p5+3P79Ey9IukHGqw3ZNjTb7a+SzzV7FIgGmvJeQzc2LO+OPVpVnoAOzUoUD1eUyff4TQpMqRWa0rLGQZ/K/lOmf0LB2aKY/1m1Ykt0qExNUtiyZtmWqv+0RE3imtAEA5Irio4HmT7KdcDo0dvQ8SNnDgIyK1ooQz0+JhvvkgFcFhdvJWNSx2zlR2flCuRIsejbbC5jjZY5IwWRyx/P6uusrNEyrpJk5Sftv3Q3Nx0sicOrGjTZKykpML+m9bT1/CF9S7LILiP6XLEcz5v+5P5KFkJJIrY4k0vqnGFB97l1yD3bU7gXsr7ne5l0SSHfx1ueX/zGOpCY/+8XFuxQrkLy4gbryNtQ0VGPw3AmurpwFOWcL9wla0Bs3YuG3wNUBatkQV73qJWQxVRVwEc/iqlgEwaXY/nkVdo18kLCzbYWaBUMGqyxVX1MRmNK9XNU6vD4fnpeoX8575bRv4Jz49NSE87t+G5oO28q3FBmDq6yqOyjs3IF/XRDhf6jG0I3dFA3lNG/ohsSzmAgjiiz3Fa5ouzyvdIZ5R6eyarpqUMqjgK6JHRJh3VJWQ0sOCUWDg/DI6XxusIdbSP/KoPKPDkrld5PL5TvPLogdEEHdUFb9dv6H47W29cEvMYL8TaX+V0YNV4v91IS7LplgD1n05eVkHL55XrYuvmpSw0yLkfH078Vz+pwz9wrf8t3KqCK6AXOQnG2kOlcWda2DdycMsAO3whvYduXO0wg+qlpFwgzP4vJGigOnAHDMmAijaCtiXWx3+KkmeztzCvGisv8If8+UmhOee//CoTwMRYHUAvNkx4shf+m0ynK20TeDQpP4edgD0rvQ/7b+sUHotvM+uXnm/e3su1ffpJPWczCncdQFvA4gFimLbE9JSsqEOQLoJ720nIf/SAkX57daP71TMpO53vUkTi5D8ckFsRhEyGb9OmcTdc6/modT6yROyXTiaQYtlGdEkCWLvEWnLEwngDZPHoK1vQTSANyYduLYP3gEXvtw4HPeQAb4faFpNAXJ3Qd+iTfVX4JqN92/I3F1kex63isBlgbLaknjyPeXNhV5j26iGQNdUL6UgwnTiXf3j6xBoJDp03aPswSkPBEJT7bxHZ96/OGVuIXyY+8HDfHtmcsSkE5YwU9BLTv4hOqNwEM0VpyeO0NNIbb/YXl8pXNdAfX8MZ6nyZc+C4UiwpOpuSkTOCB0OkLjve4+dwXwdIidDipKk5lAzW6GkPmhsS50IWLS0dmYgWq578fp3rGxgSyQfCTBVTCLKsLW5U5lhcAacV9JhOhkG56fuKZ0Hjq0uKodgSEvvQgxXTwblE2O8pbYOQtbfTEzXhiE8psRhcn1pcdgnpjXZzsoIpfxxID/eV/We4z9eIvBI4oXlrzJzL/xk3V546A+t3I5UNNJwl+lNF6hTOC8zkNW/0YaN2Skjnfx7Eerz+/TVINsLlpuutY0vgvtZnyuGa/mcmsZdxAfanRGNWnsfndDP2rlP6dnjRM89PIfcpEurRWHMATEIm8JNMzyXb+FUZkZkzITEszzdM7Gvl5q8xQ0sGRN1d74JotHkTjdM8lfkf5rPo4mXo09ht66TjKJb7fkG5r221I88IQ2pZVNjji9hHWkB9gaajJ8sESlsAPg2QiyR/GWTHsNDHHTrMedwpw7uYn8boyw4KdgwE0tWQQDNnShcqKFuIudp6d2VvTt+yvj++0fsOW2/XlTsl98tNcRgGrVg9j1cHpTCnTrO3p21cUL1PgckEmleaAHMOK81IvVK6GgtLaC+8roWVlbTwEyKNQu1TFWeNZv5KZWs1XLIpJ5Y11x8nA6bGcJM5gJ5HZELOEcEkGPqa/F5FA0SwO7kO6GR48uI9PsaIiODZNQ5r5OnTjDaxpEpQvsr6D2uaOz063wTcbKw7hvBBElYJ9mKSpTLBgiCkVNUFDITimzZzTGJbHpBEctWaB2qSQ/w6SPoWE1in6SGN1Z+2xJILfJefiFDU56/hpwjIQvpAwhBSEbBhAZLDAZYEYj/NyAyY/pf3mTHlOnQ89z/VQzDR4P7GegldAzSfsaPl9Vo/u2UIQ2pIct5IuBnlFgvq9HZnkaPlqHdI1JqudBqbi9EMkAtZsqlGIXRWFl5oNQL9v8VwWhTYzmGJqbmOpRZhYdMYVVVhzzmnJEqkU13hayzTIQ1iaY6Tc7/Jsop61C2mzskNlkjxLMxckfq2A32uHlGvCDyzuCNahPJ+nNImncBCpbUrAnW0FWx3NnW+ICDXLOHSWcOgwDioTuyn7mFe5iv0KtofYmv8uaku2Yek3svWWyO6mUDGj3G+5Ld+iXVZtKm8Ht2JjuaTBcqFMlEkD2RDMcgNllNcwZ/9/nGXHTJJOTvY+XWCHG/vBmX8LlkvFSItvp9/z35KMKa9PrkdYBiydCrDilQGMMqviFqFmGG1OffZOYlm1NM0ns8znGBIhykVFKiZj9eGQEp1k7LTx9uVZRdnpgMoynTC4dpvUkm0Jq7kWhYKTJmifHU//P9Cc6gK1zeOFJIkhK8sSARxksbxgQriYGL2T5KiUxJa3AU+eYlROIVo1emc8vSEhXdu5/yK3wU0cUq9flcOrcPK/MpTNegH9a2O9VnErgxVV4hjSfDY2QOmJ1l1Wtu2N9dajvpbNb8J9iK0KnjoIUs8YFEJtgkP6tBifzcLuM1tlU0M3eH3hRtRX+GQOiRYMVL/gDKdz6MOoYtC2mz/wIszfsD0hIgk/pqt8vofDCjcoaZszDTZZ6BrAI6wQkW0Jlu7ASzEoKcMHsr6RDVvHMiZNSOaQfGPx7zCwIUs2blAcRD4PCSsmzaaXbGXxqSvi8jUobUSDLODqeJsxfTdkuaHWNARYwzaizxbesdjeMihNRGR8v7KUv1yxQIQOlRV9+ncnYkDTNiHl+fjSyNZhYnL9NTk7M/EiqWVpcijmNhAqUpUVy51+dkKeH0q4HUlfq9NSJf9t2LZs3oMWM1Bla1elz8rliJUd0K7ICysQgWy2eeoMcqbO07/wKyHCl0JG83w5/ElwKrQcvnFIpo/TCc8w4zLm2AMpJpjJl7FeUddLaMgOyQkzHs6Pubkm2fI0RcBRRQey8bMN738CrMDfD9gNExttPj11bhm6+mBLQFYGbIbbfPjpcpQfxK/Qay94hFUVO91fPUOeJ8wztskKbZcum3jmj4j/syrhI+fOLR0XrhRhyz/HSnuTHHu/+I398XtlGkfWSnbXAR/V6fS8YrrUzpYsE3Jp1qiw0tRHaCS6TXw8GmtSH4tkMnoZvqGhKsuU5MZrkTJcKGRySQo3EsgmSF4nDC8QW3OFvIJTs5yLfFgSpdwmvGCLC34KHOaKUbKY0A+Xu0xKNgJT89TW3M6VyEqXy8Bo5NX5s9UrtkxezzpNk6SZqKy7nL1J1zp9/sVimpH/JGTF9CQI3UcXNnCXa3/OQdEEcRUEDjpbB3SSYJmMwMwKJSWqD64ByBfcY67FZR+wqriIfOcbsQFGvEhJL7KrTOBhqCavk2zmTPaQatDobsPNbZAmQhToxknRKKUj0F1apaK5bdEsT1c/eincKsEh3RHpjkh3HCDdUTeLdZD+2JpHRJphl2mGOi09BO1QX38tGqKu6KZoidrmnyJNESmFckqhTlGMKIZICkRSIJICkRSIpEAkBSIpEEmBSApEUiCSApEUiKTArpACpSHefiRBXbSIpEEkDSJpEEmDxyUNimtXk2s+plRuMb/G+z381R22oHa7AtmDyB7cgz0on+mRTYhswtbZhFLV6ya7sLqpyDbcm21IbR7iyfQa0iQEpVorHffGCGcFhOWEiYmFZvaFoFhq9mGIiqeoN70WtqkgkcCIBEYkMA6ewCif7YZDZDT3lEho7A+hUa61hyc2qtrRIMFRXkU7REdFd5DwiIRHOe4qVxgkPiLxEYmPSHxE4iMSH5H4iMRHJD4i8RGJj0h8ROJjj4mPBU/UBAFSHj0iERKJkEiERCIkEiH3IEIqtjuQEImEyNqEyOIKAImRSIw8MDGyoIJ9IEjqmoxEyeaIkglkomRMFgRRhwFHXeaPdBF8vfZ9+vgHEs+fToswKRmADvMkpa1tjR55qsrR/p2tkUf9kw1LQDuCiXERKWt1/bip+1brqk+FaiDPEnmWyLMcIs9SPUn255rsXrhcZG52mrmptoODEDZ11dfjaapLboyeqWn8id+WXfZMeB/2rlxOtXYZX49dFsOs/BHeh40MUGSAIgMUGaDIAEUGKDJAkQGKDFBkgCIDFBmgHWeASgLEPYmf6lAT+Z7I90S+J/I9ke9pxvfU7I0gzRNpnvvQPGXTPLI7kd3ZPrtTonkdJXVWtRS5nPtzOWEtD6tMO+Sjay9heIHBKRn1Gty8H0h89xR45EYesw6YsZnreXepmoVmtsXRPD096JUwVYJCqiRSJZEqOUCqpGx26nMKSlPPh8TFLhMXZVp5CMaivN5aVEVZkU1xFKXNxZSRSDNMNESmIJgiEgmCSBBEgiASBJEgiARBJAgiQRAJgkgQRIIgEgR7RRDMhXb7MQNl0SFSApESiJRApAQelxKYm24eubdi/lJ4ru5wAqX7DUgGRDLgHmTA/JSOLEBkAbbOAsypXDfpf+omIu9vb94fBIqvMKo8NoMdo+ww1yB4faAeCfDq96lfPSWyX6n33SX8SZraFunvNHWid0LVCQwJgEgARALgAAmAqhmrzyTAXbwgEgG7TARUaechyIDqumsRAlXFNkUKVDYbiYFIDEy0RKUkSA5EciCSA5EciORAJAciORDJgUgORHIgkgORHIjkwF6RA0vh3X4EQVWUiCRBJAkiSRBJgpg30IgjqNyOQJ4g8gT34AmWZ3fkCiJXsHWuYEntuskX1DcTOYN7cwbBf9jgPba+kCpqabgb4IkJiZ0kc1D0vfu8wbShbbMGT0kbeiZQtbCQL4h8QeQLDpgvmJ+nhsAWrPZ/yBXsA1cwr5mHZAoWa26EJ5gvtGmWYKHJyBFEjmARtsyrCDIEkSGIDEFkCCJDEBmCyBBEhiAyBJEhiAxBZAgiQ7CXDEER3NXjB+YjRGQHIjsQ2YHIDkR24E7swML2A3IDkRtYgxuYzOvIDERm4MGYgULpus0LlDUSWYENsAKFf8xwAsUY1+CAwcb3NQDKEfWAP3F6z0nRAmUD0F1uoLy1bREET1Y5+ijaCrEhXxD5gsgXHCBfUDOB9Zk0uKM7ROZgl5mDGh09BH1QW30tDqGm5KaIhLrGI5sQ2YSJomj0BCmFSClESiFSCpFSiJRCpBQipRAphUgpREohUgqRUtgrSqEswtuPV6iJFZFciORCJBciubCj9xPrtgW6QznUtRJ5h8g73IN3KJ38kXyI5MPWyYcyzesmA7GypUhD3JuGCE6KekYxuHbC7JlJ2UbbfgIfKSGaeJsRQDsFL0qdyTr0UxneEefbNVnSVZg/J1P7evvuWQUGwWCjSvxhi3Xw5zWBag5J4U9nPyoQG7Z9pmYf0cj2Y7LapEu6Qmxrv9JeQqW8m5fy3uffgZG0bdd3aaBVHgtoXrkH/1b+yKjm8muZpbOMPZP5evpx+3dhiC6lzZ4WRoPqVP4DxVvZ1fws28DyuEXzJ7JYe6TOuNEVTtXeIixsYFWU/rEl4KRfwY8F8bZ7ohJ+jMIWbkQvysOot6EbZe9VIjCD8eRvxk70LZK/AGM4gx/yrzMinJVEXAkOMjmvnFe/50KGLuwsYXm/hyTeLb0VZiJTGQvc9HJvYl5OVAwhvZTtN8nHSuyRhvrtF76GuV77oDXv9YuS83vW+/E9FJkCBhwZidarFT8g8Mo3j1MypG5lf/7ZI7CFCZP0kwWIA2yTZiGWDewJrSOx1Uk7y9AbTYn0W/cZmgIxGYBntIQ/nJuSToSm84WwGPnvac03YjBTeTFpTHPT7NSWK4danRMR6UxAq6YZLdtBh19DNyYHU2JmnFBjeCkd0Y++5/rkjj0Bm5cQHn4xffCaRGsv/mrkXzkDvdyNLW0X9h+ktNXtI/YvPuyczyoe+vnm/a3alg27dWRj52oyZGt/Y90zqibrYiCm2kuOJwXPbsyQIj4O4b2UwJ/4C6Cp8B1lWhLtgATghppsGkvZVcoTkijwXgiLsRkQxCvhtC353MdaOGFVGO1j1nNzrDr7xfFcuuagqxSbLJdkHkfdcX2ZQZHvfYIsQmZkMyEXeQXAgOZ0XsZDKjZr6nivzkaxIln7bmbYZru9zGpeBa4fz0Qvp9uPZFtW4zpnrZgKNHi4Kp0ZbkPHjxwGKuxzTkH6sJIpv/PxO/b7OOftCk3gSHzjZ+hOTK4NCkmxhoAzXnqa8H9byQpBsgjIbhQri1m48xjKmlhQYEWJtZSpqCh4TA+P6Q3TBcg8fgcPqA3R6wz2XFlWlw5xkCxfX62TY9milCdbdjsplmtd34+G5c9Gbf9FK9IXqKInicazuYe2mpmU7sHsWRr+8P6H2Mrs4xM6w7a/yKTn3LJabnSwLXHfM/ihpgOm7MHkD1PufQtHvfRowZZlWwjpFbFGYUkxqRrrSZWoVQ9kImvbznDCd8H5e7UpzphpiWrWCBJvSHy1+CdhO92nhwFke39cKCDfkpYQgdMUdvtLdCcZ1JrrdCd8cOPQCTcJyUVZnpKlKtHo6c/0B1kIgoxBM0I4O0iHZAmF/oXGtlRgC2VTaBO8XSKGPTVdocWIWiBqMWzUQmLR/QEv0DM27hkHC6lIBHQIZEVabS2ARVJiQziLrK0It8gbn7oeI8yl5GCM3pL6A4RtugXbSIzGGL1JlWiW/qXGcUo6NCt9on5Zqkoz6af9g4f0gSeiRG2hRHTdYW/94CwXOtXAETLr6NPGjxQDcVwoSdmollClk9cGDKM6FUbV1/9q3UbYCWGnYcNO+qkNESh0nYMGo/TqfwhcqqoFtSAqfeENoVUVPUDgCoErBK40wJXefhDDOiyGZRzmIpzVFpwVb0VgF6EthXhq4Rqb2+AtpOAJ1/NYrK9PEeOSDMOxES5pk1rDt05aD7oqxCoBIUSDEM3QIRq1Z+7qBVx7Wv+AcQa1DA+DMujqr4kxqItuDGHQtP6k8QWM4LsRwav10/BqrC4HxEbrYgyH2wuHN3DxwjwRQTLILBqWyKaxGKiwoDn1mLhQXJdi41LTDhIjn6x+dF2opgLD2Blj51OKneUevF8xtLFXOJFYWi7Tw8fUqnY0GFvLq2glxlb0BmNtjLU7FWvL9XRgMXflOhtj74PF3smKRRmEF4RVJ9iisvox8B+v175PH/9A4vnTCcbgklE4cugtbVFbEfdJK0H7vOHIo86IXacgGEuRslbXj3ci2dZTkwoVwNAdQ/eBh+5qx9+fYwldcS/DBQPUWnIQDEBXfb3QX11yUxG/pu1I2pc3vmzPyKbvGD6g1mpjKn1ZyrPyRz2kthvFEggmtAYmwHjB7ep2yCVgL0EEACFIJNNc0MjvHTp56IAPQ6ewg6RJhwEPTk0PuirEKgFhbI+x/UnF9jnP3Pnt+N2s/1Qi75wMjxB6F+pvMvbOFd1O8J1vPW6zYxjdrTA6p5/93143WxdjJHy4SJjf5FkOhbls6lyPSOK7p8Aj7JbTE7z+Mtv9I1+DmW9KW9dhnqa8uyY0lUAwtsXYduDXT0o8btdjWkMrH+41jxKZHeS6R2m99a59lBTZ1PWPstZirIqx6pFjVZle9j5GrVjHYmza2pWLJLZfYeTtCIYe1CwrihqhyQfH9e7oJPn+1zlhw3564WhpCI4bkkqa01JYesKy76LwdILBEBVD1GGHqCov3PUwdQeLH2yoqpLdIcJVdd21QlZVsQ2FrcpWY+iKoeuRQ1eVbvY+fDVY72II21YIu6SDb8OSji4lxPBTlSuJpIFw5uohCGOyON1AVgxAN8LYtDEtB7EnJ/XuCU4tFAxfMXw9jfA173v7ErxW2vrgQ9e83A4ZuBZrbiRszRfacNBaaDGGrBiydiRkzWvmYAJW5doWw9X2w1WHD34mWBXiqBG0JEuWNqKVw8acSW3HDTa3rWgpyuy/wDo09JJhxQARA8R+GIzC8XU90qs2U7BHEoZ0EIRd2NF6tfJYuDdSLPJp/EBVfPQlt5LMhFzx2FrSlV4MCvhFJ1F2oiYR0W7gwNevisZl1lnL84tkAC64Tr+Kf9L2U9VeUwE+ULunQe1i7dHJfkmXjvSpi9+KYeR4attgx7b9+4X14jrWPV/DfaFe7us0KWDE/jlOR300T7rGv7g/l7ZYHQKY92Xu+Cy0ot0BFUn6ou/J+dleq+D91qNflD00t/nJDmWYuwL476v8Y5VlzNQmI1sQnwyuUnCPhwBUSlXWhDuK5SHOoY1iNbdA56PcaOW8+qOMc1S+aORO9PN41TsGD44NcQMEcIwAnE4pjbD1gqkbJ2VjitCiivUXP0nXJLM0yKsRfr9z/EcSButIJZChb+0XBuC4aEupMS2BLicr9fZzAFODdhZO7NTI/Mt9OWt+7VKEAtUrBmCQmkUIOdcs5YE4IQntOPhG/NpDA7KuWch67S7qjm28fqhZRGarQFlSFIdGjXFiYmv6VF1MQ/5M7asQ0ERAc9iMF/mSpD9p8HEKxCkQp8Bdp8DBApZyd3YI3FJVcy0imLzQhohgihbjBQ3yxiczzfZaBs3Did6bPcvN1OhhmBuMHkxukTN5NuvnDZsMI2j0KPhss55Rz2z0YMb/GhbMvSzep9Etup/c/xijtok9zpI/Jpo9V1b0LFQBbsUF3Cz5Q/0oGOIMfqgfESY4m1ftdmbtb5b9h66lIIAZ/6V+DKxvBj80HaF2N4Mf6kcyFjfTcgWLC5tZ8kf/rjSphC2RtdnWrsMiGXqbQSARdRkFadSAo2/iICTXZL4OI7pQ/YljLae3FSEdhuNuSCia1NK2xInrwSGQGTakyqogU3M05TVNH7kO2KuHv06LQtklAq6rQ1X6gYAwAsLDBoR1E0OfYOHuO5/BgnA6FToEFKevvxYgpyu6IVhO23oE51TgHJ8iEeLpFMSj0+UdgB722kz87h+UYBhqIKDQFqAQgQDowAkJJDx/qqdS0dSIKq/pUhLBBdkoHBdbkLeoJWjhtJWgoyKsEA8G9hjYDzuw1zjlrh973c30BxtXayR4iLBaW32tqFpTckNBta7teCIQ4+Qjx8ka9ex9+iOz1TAGv20FvyEdf2nsKxNMjaiHrleiOFzP4yt/gZvsbNapHJLjBsUGzWspQkZdOeBe2IKs4qcanPfWdGYXfcD4HOPzYcfnppNFfzbhu+J4BgsImKrMIdAB87bUggpMq2kINzDuFW7MyxvPfABuy3cLbjDVauMteiblGfvZv+35PYIRRCvaQivmiTBsx1/Y6o37SqFtx2DuUZ2y7Bu6CP6YDFvsbUZ29l/UgefPINCoJM0DKT2hbbQEen3SnJwWHy/owjp2n0n6x3aFl34FPxbEix2TJKFUva9T7Wb9vhE9uVSZiMG7ciuAkShZlO2sVh4EDLSfysM/8jdjJ/oWyV+AsZzBD/nX2UNKvGxTI6nCLkAX3KzmMPFbNKZ0Iv3RbSErqhnWU/Aqi1kybZz+nSXa0j/z+f21fffp+j8//PjpTif1rG7npZ4Lw/fsOu3PN7I9/Q4HzKa//PLxXVe7WerGmd6azUV7pnEA2SFS2H46cvICs6NZHagVBrlc5H4jqXcRH5XDymw2Z96K85JZy9VE6SLgnmYel/skJr0Z+yl3FVQwM/p/+Zd0zGf0/1V5X8d57VqR0E6y5e3qH8bS8WY+LKe0rEBJvZB1mfnatio+k45weYRg6Krt+uPt++ur24+ffp7oBtTxXp1NxHq0dzOr23P1493Vf90oGyKWDr/QRY/39gnOIEY3dKSjpUuiUX58fyA+Cd15EqiKd+gCFRC/W7qa/VpcYuQWd0JmVDj5Z4qJXAzgq0IBoglFfUia9uXL10nhqytYL7Pv1J3JY682x2bhp+ad8gqLLnB9l66Pa6yw5INYnRFnr/TUbQ1muSajAS3o7eWZfI1VGiJq/qXPFO8maSRmyQCqnhPtggfFn4onoU/0Kfil2g6Yc1OTGX8prCuLM3HD0XQNI2YnpWlWoaXR0C1Ztcf586Mhf4bhZtvBqAzgtgMTpc7H0GBoWxcM1lRrrEa9LDqmXlnLytPBVnKwpRDSkFkBiKW5TmZCfPnxGo1VFxSkHRklRVTfF5A8qUtg/MHxInJWU8UOo1rJ2NZXquy0VpyU8iu2S/myz2gea8PbG7Vuv0lC6T7zdVLNzX9Qy+mWxgjYGjsYd70pTRcPSNc8mXNwTky+XjZ334RW87+Yd/BrpTctOKzU81xW5zmXQhZMYqI5agxyl1EeVeEbXHlmOzkYo2Q0yWjMDCawnCpUjvpu/BBW9gFu6dqd0sN+H/matF0MVbSXT4RfGyfydE9Q7W9rA0ujZuLHyqylC3ceQ1kTmKe+7rJP3q52bGWOhBwk5BzNmmXeuD+8mBNyIC3eP9b0mnAXFkpW7xpimmSLRDaJovHMH5vk/Cwna0XmSReYJ1ktN2aXgNRn8GNSNxloc6Ggkk2iWBEb+zUj5ogRe+SwwaiUm2ISkFaOyD5BaW5eGhZDhmWrSiyqRuh2G25ug5RGI6bKTsbc0pb2KAZXtL+tmLz7gh2GVNRjjbExxsZHj411XrPz95y3acgDjUl18m4oRtVVgWkUMLo8dnSp00/DPAqtx4eGqzOMFw8aL2rnkGHFj3G4sWM2MYmDFluKl3QUGotECgdnexBqFlrc25Cz1I/DhJ5dFviwpFQ99hiSYkjasZBU7l0HHJqaG/hJhKhy+bcSqsqrwpAVQ9ZuhaxyPe1m6Fq5usMQ9oghrGKuGXgomyRpUsa0hWGpE+pQXf0x8B+v175PH/9A4vlTN0NaSUP7FMlKm99aANt1qbbPTow86gBYwgka98Cxq6ipFF4HlbtSmhgJYyR8/EhY7ZT7w2Pup6cYamyt1qimQmp1DUhYVjS+bCLISO5YAK7WamOCclnKs/JHR2Mkm61pMVo/bLSumbQGFqSDmni0q3bI+2ovobMQmkvGoM5ZVBLfPQUeYQeSu3l4ONvCPh0izre7tcPEnRVgv6VQHluMgTEGPv7hXYk3HNTur6nBDvWQrES+TR2WlRSNu7kYTB79eKtEL7uye1uxusL477AHVGVzw8AOqpLYfoU+2hF0Eqwk2+kagcIHx/Xu6HLu/a9zwlSsk9FeqZU9ivgkbW8r6uu2MPsvDfkYYwSIEeDRI0CVhxxUFLiL8Q40ElTJuaFoUFU8RoQYER47IlTpZleiQoPVF0aGB40MlfPFsKLDJe2mDSsymyQdpVZT6nwDgcXVQxDGZNHpGFG0sYcRYtrytuPDLoqx75KQjS9GhhgZdiYyzPvFQcaF1WY78KgwL+OGY8J84RgRYkTYlYgwr5ldiweVqy2MBo8SDRZmiaHGgg7vZiYSFB2vEUBc07VP9ZXeHQgGZQ3tUUQob35bYWHnpToImShHGqNEjBKPHiVqHOagQsUdrXig8aJG2g0FjZoaMHLEyPHYkaNGPbsSPpqtyjCGPGgMqZs+hhVIwl2sVF1EV+1kvTiTrmG3/QT95xc5s4t2re0VwQVjMFCZUcWdxTP5Xb5lHZJoyzjf5Gj+RBZrr2Bg5fILqRten4hftbBZ0MUlO7yc/LFdT6VfwY8F8WKnvNzRLXVuRKt3GdnknRG/8tZZrTxY/9ImUwObJBfLO9G3aMK6N4Mf5Quvt1XXvps634Qd1ol8KXa1ff3jQrJUYn1R39muWYbdho4fOcw8xUpMvhRWLNukDydptaaF9Flf06XTLbT3Jl4/fDW7xrt9FZQY1g5Syrw1/bj9W7Owh49VN4jnlYWWkf9A8RbTAfow+626m5wOJH2E+NE6JPaTE7Eh+RdtyyhjB/J3M33M301enACEjNO5R2hnF68NLmt/r654Tl58iO2Xvzje6sn5y5QNtr16+OsUjOzjoj93ONcRxqnewtqQBhSlawbXdVLkeNdvV7TMBFfKBjDWbuuUr2MJQPnL/7Lc51VIXdgzjTAuLbqCm3/jsKdPXBoJhNYqiFw+EpYTPq7hOevViSxnPqeTmh9T0W0kJT/SSIDGs9bj9ee3ltBIZiTTXTvu0w8TlS4PQvabmfS23wbqy4AZBvXh3ceNAG14U3GXwLZe30Js20kwbzwtsQDoHY2EbukfsFMOv/83lQMY5cjw2akfvI7G1h+ziB6EDAUDVgxt9pWJOjgrQ0xMMwsFyAYlGced5mruK38IV/OfxOtKN2Xn8Dm7mQBRCv5Jqn4gTkhCOw6+EV9TN1skiPbL/Kwt94NyuzebwjPWWrUWkttrvlnTrI/Tt68o9vxmRVqQSaXZ4TWtOC+SQuXZL88kC4qrxSKB5GBz2/WXQfjMYnzAO8W+MWv+9Kyiz3KDG5Vl8UQc2OSe3l7d/Kd98/bv79/98uP7icJcty5m6kYBb91ozMdt+x23zYuLsQQapo5ilGsqdfnxegW7BlKnBmtKagWsT8WdA7berNyHLLdBd8N65V5BxiJnBeOXv5C69Gy35Y9m9WNW1CWj3VABgmbGDe8pt25IfLX4J6GdfCFdhYyybTwh5KjLomk/tHeSrteM753wwY1DJ9wk+1XK8iCVZjTlbZ8+ct1j8pXo3/Rn+oMsxF6XQTNC8gJLAGcJhf5FZK1VNoU2wTsKnpXTuQHAWhLR9QfdQhNAsK37YJtENQ6BuUmrrQW9SUpsCIGTtXUYQFzqoozQuJIjMnpL6jcQ0DscoCdRX2NcL1WQWfqXGuEr6ces9In6ZamazKSfInCIwCEChwgcInDYIHCohysQP+wWfkiDKnu7eJvlAv86NzxuQ6E+IIuK5p4QyNgTgSHYMky8UaV+A4Ae9b4FUUg0DEQhm0Mh9dZ2CECyqgX17h/VFt7UFaT6HiBiiYhlTxBLvSYjeIngJYKXCF4ieIngpQAvjWEQxDE7dv/xVnB2EdNUCLUWWra5DWh0Rf3neh6LMKu74KaksScFbfZAWB0d6apRHAQ+pzaPruY3Q5jp6DCTWmkOAzLp6q8JMamLbgxg0rS+R/ASAjjtAzhqTdk3GxviIYiHIB6CeAjiISZ4iFHshGhI19CQDe08SJYLLpExA0MkEm0sui6krusHJFJo9MlCIx0XXs8gkuJoDg4qkZsNQiYImRhAFnLlOTx0ompHgxCKvIpWoBRFbxBSQUhFAanINQahFYRWEFpBaAWhlUNBK5WxF0IsHYdYkvT9SqylIOI6YTtVgR8D//F67fv08Q8knj91FmqRtPWUEJYeiKr9s0ORRw2bL984eTlS1ur68XFOoMkENQTMRm1//Tl71hX9QTioOThIrZcHQYF01dcDf9QlN4X5aNo+jMNZZXvHU1MHRIjU+mV8ZKoswVn5IzzChLgS4kqIKyGu1CSuZBRxIpzUMTgJxOBRsdkhl5u9BMEBiCSRZ3OAxF3o0hm/J+ARb+zpokfdFFb3eTnSURwetpMzD+ThIPBignzklOYIyEuh/iahl1zR7WAv+dYjzwZRFBWKktMU5NcgDoI4COIgiIMcDAdRxU4IhHQdCHllkisjIVyiNaLrH0h89xR45Camc1FXIZBcI08I+ui0cDoPeeRHbwBQh8wMEOJAiEMKMciU5RDQhrzeWpCGrMiGoAxpaxHCQAgjhTBkGoLQBUIXCF0gdIHQRXvQRUXsg5BFtyCLRxJT/07lZUcgMJg/swKsEQR/cFwPJrP3v84Js9KuohSlhp4QUtF5IXUerSiP4AAQC5VJIGqBqIUUPVApzCGQC3XdtdALVbENIRjKViOKgShGimKotASRDEQyEMlAJAORjPaQDIPYCNGMbqEZSyoy+5XKzCaJ0KhGlATZQMB89RCEMVl0HdMQzTxBRKOjAuoNnpGM34DQjLwxIJaBWIYWT8iryyGRjGLNjeAY+UIbRjEKLUYMAzGMEoaR1xFEMBDBQAQDEQxEMNpHMJSxEOIXXcUvHC6yDHohhFgjNL6jTV56dBrrKGiRtO+E0IquiqTzMEU6cAPAJwp6j8AEAhNSeKCgJ4dAJEpV1oIiCqU1hEEU24jgA4IPKfhQUA5EHRB1QNQBUQdEHdpDHdQxDcIN3YIbXoWkqPQTodWIZd85/iMJg3Wkmlu7gTIUmnlCYEPHBdT+VRyJe6hxAQf3Aaz5tUuJVrQDpGYxEfGWNYsQ0qtZStaZ1h4akHXNQtZrd1F3bOP1Q80iMvOXfgVp0Bi6cLc1faouph0oruhWBoDIyeeI/tw5hI4OHR06OsSrj4tXy73oIWBrVc210Gt5oQ2B2IoWD+NKrCy+xC/C0jycaKnZs3xqMXoYJhCjB5NLUE2eLaJYBk2GATR6FBy7Wc+o+zZ6MOOkDQvmrhhvMDvcjoXcExhfXpaiYckfE+WjovJZqIJAiiu4WfKH+lEwshn8UD8izGs2Vy3apWhd9h+6loLgZvyX+jGwrBn80HSE2tQMfqgfySKVmb91ZXJzmiV/4CVyuP+E+0+4/4T7Tw3uP1XC3LgN1a1tqEUiMHvJJEaVoSDDGpseN3EQkmsyX4cRjYV/IlHkPHY2Ybq0sSe0Q9ULYR0CvmUdV1YF9wxEU17T9JHrDhNLceiOsh8gF+IAdgV01tmnvYHOKxdisI1hsDqdPQQSq6+/Fh6rK7ohVFbb+qFgs6xTiPAdDuHTadUOOB97bSZ+I5KESBIiSYgkIZLUIJJkGI4intQtPCkCsVF5CLnZyRJnJg9Na+AV19Qo+oItydp6QtBSH0TV+VPX0kEcALKjsQ08jY3IihTZ0OjMIYAVbfW1cBVNyQ3BKrq24+ltREpSpESjKHiSG/EPxD8Q/0D8oz38wyxmQvijW/BHSKUmRT9k4qwRUdM1P/WY63l85S96xbKpbPgJwSK9E2L7BIkFWcVPNU7DtQO9VAtqADiMqWX2h21zRGVCrKcxrMdULw8B/Ji3pRYKZFpNQ5CQca+GwbphbgE5N4dDkkz1y5h/wyQ4Yz+Re4PYE2JPiD0h9tQg9rRHYIpAVLeAqHkiQtvxF7aalVMp6u0YUPuz7u9Cl8/ooDz31tzxmdmDx7IcfyNaGtGmWvf2jVD5e9rNTDGrkLxA5OFYr6w0a0knfmsRgE071v2HIJiGZDka39MSF1YcbuCLXAmJLU2tvwevtLBwYr3ScXZooXRAaVuC123p9JPk+UwRMCHCS1RNtoMlWnBHnG/XZElCqpu08dC8zJv3cMQ+aSGVM8zh1ElAYUKFHOg7fUjZ/+CFKj+LoKzIWZJ4w8M01vCItSA/zNLOW6MlLAFjaM54K/25R6caK1f/KJUEXcLnj/8RcE2u71KbHUnTPpVNx1mtPHfO3K4uU5BqIrzavv5x8bVcPPNaxVLf0qFxHjzyZbc4WY5VJM8neTd1D9PPSUi7M30v/kgi8DR8AggguonXD1+NQAnQu6oxSxd4yR/bppXXfmpIxCQt1E7rLgV4Kp/zmZXwOYi+yn4rnmGmOLOIH62pl3pyIta5f9FSR/DVjK2XFe9ms6rMsj0u+m4hLeapQJOEntWAb1mJbUC0OePXq3ATkDz7fUKwe9/l1j5w6jvPpGYiucosiAt3HkNZdKlECzwKrM8V4VDQ/XG1Q2bs/UHyh6SQb6xPvrex7vnq9D5ii9z7eCty+lH0FKxp9HB/n6z16FJzYjmSsu6TPOL36UvRynn16QvTdnclcvo8sXbdvzidDYysyR1ikyJfX62NiGxRDW025Fo3jA0F8E5GKf3KuRhx86HtzYesvhlvMIBEZ/BjUjfX3/is0l4y/sPU3SoMR8APIw4EJieeSfjizkWcOqrMDJhtT0UyvZAss49P7fRjxVhMFUtvYwCR1S2mxFlhd0Re5Xgq0DzcEcIdIdwRwh2hge8IJQh0U1tBGo/d4+2eXm3lsDxQyYKmToI3El8t/kloJ1/IAGDLbHdOKU3fMKTYPmbkJKNUEzhywgc3Dp1wY++dvU2iqtOf6Q+yMEvnxh37C6wWnCUU+hc7IlQM6s032gTvOAkIs+p5WtCqRMr9QVjRWhDwRcC3obyPZQU+SLpHWbX1sjyWS2wquaOkrcMAg1NHaoQIl9yl4T02Eu+GoPIBs0iW1dcYW04VZJb+pQY7S/oxK32iu5BFoiYz6acIXleD1/rICzFsxLARw0YMGzHszmHY1Y4boezDQNk0vLa3C+RZDi2qgYlm4s2BgdyKnp0Q3j082SKYN0zoW6Wpp4WC6z0WAuJoQwiInxogrvcJh8DGq1pQCybXF94QYl7RAwTPETzvCXiu12TE0YeOoxtHdAipI6SOkDpC6gipdw5S38mHI7p+GHQ9E0HbRaRdIbBawOzmNkjTB4k1ySAgd0m/TgpwH5ZcO3+xl3zATw01VhvdsG4BQ/Dz5MBPtWofBvrU1V8T+FQX3RjsqWk93leGsGIGVlRryr4Xlp00Sme0DESMDjE6xOgQo0OMroMYnbEHR4TuUAjdhnbM3ibnFvJjAJ1EWo3BOIXsxYOD6Qr9O1m4bjhy7hlsVxz4U4bv5MaIMB7CeIOB8eQqfng4T9WOBmE9eRWtwHuK3iDMhzCfAuaTawzCfTXhvsplJMJ+CPsh7IewH8J+HYf9jDw5wn9Hgv+S28WUOGBBfHVwIireHwP/8Xrt+/TxDySePw0BBpR065TQv2FJtf1jvZFH3QVf6fETO5GyVtePj3OOXCbTE8MT1VbdnxPkXVE1hCpPDapUW89BEEpd9fWASXXJTeGRmrYP44h12Svh2ecDopdq/TI++FyW4Kz8ER5ENsA8jRbPCHUi1IlQJ0KdCHV2D+o0duCIcB4I4YQh9qhI7JDLxF6CUADXlMiqOeCLr0eGh2fy2k8X0Oy9XLtPY5QO+EnDjTmjQ9oiYoHDwQJzqn0EMLBQf5NoYK7oduDAfOuRlojAngrYy2kK0hHrQnOqZSBic4jNITaH2Bxic13H5nQeHMG5Y4FzPAwso3NcWjVgnB9IfPcUeOQGJvoBwHK5/pwQHDcUOXYehssP9GnBbzLjQtgNYbcew24ylT4E3CavtxbMJiuyIXhN2lqE1RBWS2E1mYYgnLYznFaxjEMYDWE0hNEQRkMYrXMwmoHnRvjsMPDZI4mp06ay4PMtLFKywqmBsnxwXA9mqPe/zgkzvQEgZqU+nRBqNiR5dh45Kw/2aaFnKkNDBA0RtB4jaCq1PgSKpq67FpKmKrYhNE3ZakTUEFFLETWVliCqtjOqZrDMQ2QNkTVE1hBZQ2Stc8iaofdGdO0w6NqSisN+pfKwSSIQqrolITWAylw9BGFMFgPC2ESPThBh678se4OvJUN9muha3sQQW0NsbQDYWl6pD4msFWtuBFfLF9owqlZoMWJqiKmVMLW8jiCitjeiplzWIZ6GeBriaYinIZ7WWTxN67sRTTs0muZwcWSwNCGgGujLnYjwBgChJV05IexsANLrPGiWjvFpoWUFa0KYDGGyHsNkBW0+BD5WqrIWMFYorSFErNhGhMIQCkuhsIJyIAa2MwamXp4h+IXgF4JfCH4h+NU58EvvtBH1OgzqlYRUVE0TgdTASd45/iMJg3WkWrv0Duwq9OiEMK/hyLL9eysTh1LjtkruYlnza5cSrWgHSM1iIuItaxYhpFezlKz7rT00IOuahazX7qLu2Mbrh5pFZGY8/WLToDEQXmn6VF1MO4hw0QOdFjAsn3n6c5cv+kT0iegTcdsEt02qt03kvv4QuyeqmmttosgLbWgvRdHiYVw1ncXW+AXTmocTLTV7lk+ARg/DNGf0oNBro2eLCJ5Bk2EAjR6F6cesZ3SSMXowM5UYFswnDLwZ/HAbZ3JPYHwpeAoIJn+od4ZE5bNQBf8U15mz5A/NbhM1shn8mFRuns1VoYUUsMz+Q9dSENyM/1I/BpY1gx+6Xbv1wwx+qB/JgrWZv6t2AmnVyR94OXv1NmglYoe7obgbiruhuBuKu6Gd2w018t24KXqYTdFFIgx7yaRBtbYgnxr7ajdxEJJrMl+HkftCfiJR5DwO4b4nab9OaL90aHI9xA4BGyNlVXD5WjTlNU0fuZoxCRZH+Si7U3J5n9Yelc7m+7RT1Xk9xB2BE9sR0FnWIfYF9PXX2h3QFd3QHoG29UPZKWCdQrz5cHizTqt2QJ3ZazPxG3HNalzTcGWN6Caim4huIrqJ6Gbn0M0dPDhinIfBOCMQCR1rIRM7WU/O5MBGDWDsmmr6APFOWbdOCO4cmFQ7nx5FOt6nhTZqLA7TpiDa12O0T6PZhwD7tNXXwvo0JTcE9enajmlWEL1L0TuNomDKlZ0xObPlH0JyCMkhJIeQHEJynYPkzB04InKHQeRCKhEpICcTVQ3khq48qBtcz+MrfzFUMmJlH08IqRuyvNsnhy3IKn6qcS69HTSwWqanBQ2a2nt/SIlH1DuEH08MfjS1nkNgkeZtqQVMmlbTEEpp3KthkBOZ80Jq4uHATVP9MqYpMgnO2E+kKFbDoXussREbRWwUsVHERhEb7Rw2uqc3R6D0MEDpPBGPTQNTW01krBTjdgwAU+FRaZ4kWUrPU4jUYT6pcubpPJX8sQUhylNYGSNggXx6kQxxvl2TJQmp1pCpfQNNviwMHEy7LsSS28ibRuaeZ50/UJ0434bfFjhYGpmGpFBCtKFxKpX93IrWj05oUQu27ldUnZICWbC/9j06jNYruSgV8Jo0AXQhDDzLC4LVhMqYDpg7f7JA8iDgDVS+ra7YjHzlsExkXq6EHCRpyGa6daZYYU4fCfVFZwV/nklkpnbf+aXK3ABXSFKqm61utamipoUhyLR6yofbhkEejZWlMHebFrUVpWJJy7UEFHzGVmqSWMx4QOjHJKQmMf3ou7HreO6/iNGQsNamfjL2NiNJu84kL+rsZSRN6zq1ndXKc+dseCHhlPiUTSITK63vTOFF5x5d2liJRebTSRCY+FzadduWV172z/nG7Lwovdq+/nHxtVw861Wx1LfUHTgPHvnyZSeoTA/6FkxA+nCqHu/FHwkIlwIoLMa7idcPX43A0wO4Zcmc3syqXrF1JHdJMs2lZeQ/ULzFdIA+zH4rnoGBpI8QP1rTSfbJidiQ/Iu2RecZ+LvZFIqz7DgVlx5Cxmw6Av0T2lljy4uV2Mq2Vg1t3n0Xk/0+zk5lrglgfY1vS/ZcRu3vAPnOM6mZxroyB/vCncdQFp3taIEmW0r7KEZR6AfbmzymJsiMuD/bj71VvmZ3EPMKNNll7TI+nf3DrIofYo8wX1+9jcBsWQ1t9uWaN4wNPXAHRnmwywnMcfOv7c2/rL4Zb/CBRGfwY1I3QfYYN5lwkwk3mXCTadibTLYtNtVZnxrba1KEwT3fT5JAsemavXKU5A0Soz/LyGFY21oss2Qyq9dJREviq8U/Ce3kC+k/BpbtzXGhsGxLWkHEhiG49rEJJxmkmgCFEz64ceiEG3vvDLAS7Zz+TH+QhVlKWO4nX2C14iyh0L/YEaECU+/40CZ4u0Ale2itQiNPCrWTCLY/4B0aSKMGgpDiEfIfl/XmIGmPZdXWTHdcLrKpLMeSxg4DbkwdmBHmWHJThtcLSrwKwpYHTKdcVl9j9DJVkFn6lxrHLOnHrPSJ7p48iZrMpJ8iPIrwKMKjCI8iPNpg5mAtJjI8lLQYjSBYqkhfTKhNpKvEWQ6pqAHBZditw4JRFR07LqKqaFQr4OrgJIswUqdgpHq6XK2nJ4W+6r0VArFoQYjJHh6T1VvlIeDZqhbUQ2r1pTcE2lZ0AfFbxG97gt/qNRmhXIRyEcpFKBehXIRyOZRrjMAMD9XVhDYI8MoB3ky6UbsI9iqGsxY6uLkN0nwxIrYbAuor6daxMV9Jk1pCfAcl0y4KpGqwTwy0VBtbV++n20MJEHk7BvKmVq3D4G66+uuibuqyG8PcNM3HS+IQ08pgWmpNMbwlDiEihIgQIkKICCGifSAio5BtiACRYv2N8JAKHtrQ8ba3qYC3OWClY9kYjlCIQoaGERWK6xJWVGjaATCjwci6ywIyHfwTxpLkRtkvTMlIORBbOja2JFe1w2NMqnY0iTXJ62gFc1J0B7EnxJ4U2JNcYxCDQgwKMSjEoBCDOhAGVRkCDh2LkqzbEZMyxKSS8EIJThUGtw5wQbXvx8B/vF77Pn38A4nnTwPApiS9OjIkJWlRO0jUoATa/lG7yKOOgq9EOYU/qnt5egMirxDnaUFaalvuz4HOLmgZgmRHAMnUynsQbExXfU1ITF10U0iYpvHDOO5Y9gp4DvGAuJlav4wPIZYlOCt/hIcCEW1DtA3RNkTbGkTbjMLcAYJsiuU+YmsKbA0E79EBs0M+YvYShgwQNclINoe73IVw5/bgkDTerU5BabxJh8DS+i7TLgqkarBPGerKGVvnWVvmSoBA1NGBqJxqHQGJKtTfKBSVK7sdLCrffGRjIaqkQpVymoIsLMSFEBdCXAhxoUPhQqqQbfDA0Hb9jciQKTL0ysasDA3xsayBI/xA4runwCM3MZ3++o8J5bpzXCwo15RWMKCByK5LAlAN7klhPTIj6jrGYyBsxHYOj+3IVOkQmI683npYjqzMhjAcaXMRu0HsJsVuZBqCmA1iNojZIGaDmE1rmE1FiDU8rKa0jkaMRo7RPJKYTiV0pOwIhgpm6uzQ1QjrPziuB/Pm+1/nhDmE/sMypS4dF5opNacVeGZAcuyaIHSDfFJQjcqwug7XGAoeIZvDQzYqlToEbKOuux50oyq3IfhG2WyEcBDCSSEclZYgjIMwDsI4COMgjNMajGMQig0PypGusRHOkcM5SzpY9isdLRoDiOGiClgawgbggKuHIIzJYjigjuhQNyAd0ZhWAZ3eS7BbQlAP8ElCOXlz6guQoxU5wjjHg3Hy6nRIEKdYczMQTr7UhgGcQpMRvkH4pgTf5HUEwRsEbxC8QfAGwZvWwRtl2DVc6Cazqkbgpgq4cfhgZWAbMXw1Qv4k2Og/WpPUdlyYJmlFK/hM/4XVkWGXDOlJQTEFW+k6BqOXLoIvhwdfCgp0CNSlVGU9uKVQXEM4S7GRCLAgwJICLAXlQGQFkRVEVhBZQWSlNWRFHTAND1LJLpIRS5FjKa9ijKiOJcNVIxx/5/iPJAzWkWoC7xuEUujQcZGUQmNaAVQGI8H2b1FK/FmNu5O402LNr11KtKIdIDWLiYi3rFmEkHPNUrLev/bQgKxrFrJeu4u6YxuvH2oWkZlw9Uteg8bQSMPW9Km6mAZ8k9rvnBT4KJ9l+nOfHHpC9IToCXfxhIjQHx6hl3vZQwD1qprr4fXyUhuC7RVNHsZNh1lIjd9vqHk4UVOzZ/ncY/QwzDBGDyb3bps8WwTuDJoMA2j0KHh+s55R/270YMaLGxbMfTVeTHm4PRq5JzC+kzIFAJM/JspHReWzUIWyFJd4s+QP9aNgZDP4oX5EmNdsrlrVSwHK7D90LQXBzfgv9WNgWTP4oekItakZ/FA/kgVnM3/ryuTmNEv+wLtBcccNd9xwxw133JrbcatE1Ie38SYJgXH/Tb7/tkiGyl6ysaKaVxi9Gps5N3EQkmsyX4cRDbx/IlHkPA7gxgdpt467NSdtUisbdAOT6SHAaTZEyqrg5pVoymuaPnJ52quHv06Lg7wLCFhHH6pkfVJbIzpb79MGSbd1EOHow8PROs0+BCitr78eNK0ruyGAWtv8ocDUrFMIdh4O7NRp1Q6QJ3ttJn4jqIagGoJqCKohqNYcqGYYBQ8PWlMu6hFgkwNsEQwYVQExYnayqJrJo+sayMw1tcPhgW2yXh0Xa5O1qBWobVgC7aA4Kob6pIAujZ11PRmBuQYgznR4nEmjWIeAmbTV10OZNEU3BDLpGo+JDBA3SnEjjaJgUgNEgxANQjQI0aDW0CCzQG14YJBq4Y1YkBwLCul4SaEg2UDWAA5olEF99HoeX/mLgXKwKrt4XIyosnmtAEYDlnv7HJkFWcVPNU6FtiL/XWR7UnCVqf33h6PVBf1DfOzw+JipJh8CLDNvSz3kzLSehmA0424Ng7fFPAmytg6HvpnqlzGDi0lwxn4iewvxOsTrEK9DvK45vG6POHl44J1RiIBInhzJmyeDZzv+wlZzvCoHeTsG21AfYML8wJcTSBRze5kEYGeKYzp0ur08k2gKt7eRNDXZ1PFenU3EjV/UOIU7cVzfXtPB90Zj6fJR4ZhYkSuq0C5tEvN40pK9IFiN5BMGKzwtJkkrK3k4/8l4ykZb1DOWieM1pI1qVR7wH6slTAHO76li3pDwxZ1TEX306XxA7tgTb+nc6Tx45Ivpg9ckWnvx13xtBfyB40blpifDSKcH+oQUS9k+YifghP6hPHKRVUXDruR19fz8/DMJYSqyHN86d9lrfDTPLa42NLJPGlCA1+5Z9HsPk3sgVkuXFiwlreDZjWOymFj3XDD3F5Ewizw+59NFAZ+haRnUwSymxdYVfModsWhjX51wkdbueAGd7cUM7/o+CUWt99bo9cmdPxWKcDzq/ujigE7bYCOwLFnB8msxnlqf6R+0nDBYPz5Z7GXyQsJCAWy0oDLa4NCK1qsVdasL67vvLPIr/XNOrX7uQUEwOT+Rwtv3XIb31ArAyxKPNZ267EdaGGsWnfKItQhewfcR53l6us5F4jsy3mIirH7CDHAGP84UM+SbxEisaEXm7tKdi1kr2ppD1WbB1qWxsvLNkuPCppjwNVtF6hDhrRfkJm3y6G3o+JHDVgBmRTeGTFdtP7Hf0i2mtlDjfytW00Lcma81t0oQHRapTc+Umxaog63rYK+VCv7znWdSI9tpZbbfhTuPoRwaJtDCNKXtpeFFDa7edkO1bmDDL+tx99zUs9GKjmlF7ezgGe/eNb9zl1XJcc26qnbm8nWd7bvxli1GjgnvtrOWa1YZF91/5+xAu2aiGrAldQJYZdbes9q7avIdtR120465k7bfLpp0By2rR0a7ZCCxGfyoAFbVWV9L8ONdAhbcJwHe/YTG2p51/uCE5NyCwaCOKCzFw/mY8J4/OLHWvkdoDP1KLkKyRSLAqYRBEbCE2HNCg2ceslsAS0LkvYHqLLrgiGGqntNQ/dEJIXyXNSET3d7nXd+boh9OWsaKPxdtY5H1eaER2/4XIdZkNKz7NFyfnpV2U3JTYaKPl5X7+RnXa74oUWzfVwAOpc3ILPiQaUkVAGEARJSqkoASkho1wESu0lyxGpBCvYnMQQtJZLYT+m+0V1J0INRF6f3PaGy6FU68ndQpXbZ+9OnSw/Hcf5EdFCod9FTTY28z6t8gnh1u33yvjet996wPsF+99171PvvUtfaod9mfVm8d5tb4MFt/DoM4KOt6cb82ZJFs1hy1ZlKp/e3tnu68mVvAfc+a3dRsYENTtZnJkv0l67A9ULwbEl8t/kloh15Ik2Bed6HfbI9PCQHO97tBIPh0VKj3mJOTyKkG8OSED24cOuHG3jsrqcQEpz/TH2RhlqY0hD1R2v0lFPgXOyJUB9T3b9HqPVP4a0cjURhB25By78BficARA0Z7bMIeB4dKS4TRNjgtrXJvjFpSmioK/D/tfVtz4ziS7rt+BcP1IGlWxT7Te8558IZi1lOXHu9UdXXYrqgzx+OgaYm22SWLCpKyW9Pb/30zAZACSYAEL5J1yY5olyyTIJBIJPL7MpmoU69X0cf9JazThV/JWheWd+UdytVIpHf3pLdCJY2473Tyx+knNYQtzP248M1Iw3ApVGCs/PaoifV9pbg74Z1rc85DWw/1iGCuSzDvqSyJZyaeWf8eVJZoVnnvNfhmnlyb5ZurV81+veWjTRfecd4ZoJuzdmLHGf6jAYcoMRrHx0hrBn9M5LRWBB3y1EepY0SRHTpF1nzpVC8NIrJz3Fa5qSZOmxZsxwv24Ojt8hW0aaa76umNSe/yhjvgvyt6TlQ4UeGvSIWXayex4sSKHzArbgQsiSCvS5Dvv1iJKyeu3JQrr0AFdWjzxF5liPNaq4k49G1w6PF6Spw8n66Zrka05+oqSOtYCbtMdRva0PUKgR4XWa8UQKdUPeks0f+dKF2VUlH5jy0R53qjefS0eVNFP0ByWK8lm6eGy57dghjWN9tFBY/Sbu8BK0wcbHccrF4TKhlYqqZB1TSomoaa3a3EIsTt1ud291uoxOwSs2tYbaPUn29ZfaPGMqJqHFthdFcgBmd9uoCYK0boKqaqNTWWg+pEkXVF6+aaOl56tyCIjdG8pMtE93amhKZKRvTvK9C/auNKNHDLBXDgdLBaa7ZLC+v60BE9rG6+e5pYMwyii4+WLlZrBNHGRBsTbdwBbVyKbYg+bkcf769wiUYmGrkRjazBA53SyUbLimjl16CVE6uq5Zdzc9eEm4M5/RTMHy6W8zlc+tGLJ49EybWglxXyPCpWWTn+LslkUljikFlpohlYcyf2nzzxMmekfZI/j43f2m+mvxX6SfTzduhnvfGlmh07sGQOj7nWK9zGCeuyRzfnqfWtdkJPl3R6f0tbFJcV1Z7YAJGt1x2jwhPFWRoXv6LzB4n6JurbkPquRGLEeNdmvPdbpkR0E9FtSnSXoIa2/LbxIiJaexu0Nsp3BvPhhHxCnHucESSzFRPVnhLkDMeR1JRWDf2I+eZEAJsjnI9Bu0g9qqafKiaXE0cZQ0QZvw1V8tD50oyWbJkwzT27K8Y002wX9YDLek2JvMfLf2Y0gRJ4959PfLWyttX+LfF4LXm8vRMqEXlE5BmXtC1zaFueA1djHVEx29ch8/i0Fdk8PlcNCJefvPjbYzDzLmM39ii1rzk5mBHkMZGCuYF3SAaSbhK12FDJdEpEuaFbIShVxpCIyZoKfXCEpEorNk1Eqp/ZmIBUNddFrqaym8Q4HhHjqNIAYhopX5LyJRvlS5ZgByJY6xKs+ypMIlaJWDXMkFT64y1TIw2WDeVEboFGffBi5wUnwolwJtDnkmemATP10fVn6Gp9+G3iMU0jdqo5c1oQ5jGxp4rBd8igkp4Si9pS2cqUidjUrbCpOgNJjGoD5T44VlWnHZtmVvXPbcyu6prsgmHVdpdY1iNiWXVaQEwrMa3EtDZiWiswBrGtddnWfRYoMa7EuBoyrlp/vSXrarh8iHndAvN6D3Ph4L4EplLMBihLYYZaMFtnd0EYe1Pitdrzr0KUx8i+pkPfAPdKGkrMawNF0ysSsa5bZV2zZpE419pqfbCMa1YztsW35p/amm3NNtgl15rrKjGtR8i0ZnWAeFbiWYlnbcWzKvEEsaxNWdb9EydxrMSx1uRYc/55Rwxr6dIhfnWr/KrL50JiV8XsNGCukg28A8pKh9BrYf96dGZy89Z4zAwiXj+9QypxPyfklcWrEF81c/bGOp+L9RcJhxud6akHbsf8geEFXLcAvhDEjKyBb3v2KNfEAk0rtBJF7oNn3SPSseYu/D4coXcfPQZL+AaXf99xpsHybuaB/wpmNppAr6aO0881+OyGvgtXRWhA3OfAn1rufGVxbwY8ItY6Wpn7mT+JI95NtBh8JP0o30E3hBtAnlEOkVhXj6xTkTe7h26sL8QNi6GkZ3wiWD7AI7+soHGwgUGuDX8+9SeYZ88IHtTR1KJhI3cBjFV8w6wmiARkkWukn2h330I/EXYh+xCUX2OkdohVrLHccG15YQgDF7ruRMvFYsZIvsFQCSdBbQfXOtc/HiKItmJUrmtT1nlUj3S+uSkHDfcn/WTQfa6vCWSDvoPaLmGy7mANTx696XIGG+49+FJwVf/3PHk4tB0H16Xj/NG3nn3XuuW+1TVYqRs7aWDAfh2mkh5MkmHxP9ye9FSoss0YJu6cOZ8wDFQF0zGc9Hp1vfVeLSx1XYPgr7Feb4pP0intWK/No14pS3VgDHfOPG2a2i48rgX3nG9r90nnKhK2FmmgoLANmLYc6osW7st8IBmlrsiRzJSZ8CSmlNLwuDh4M03YOUUQazS3RI0OFGOT3LHK7A/OT/fvcQpmGsDI9+78wQuDZaQS9KEe2pEb9DFlNxWG3iElcVS6tPdn0SYEa8MTaPnmwSTTqgWhf82bQF6ixe1CZVq0IFPPrUSB89iigeXSn7aRY7y8a3G7pHvlEaGKTrix55SMo7yJlqZOb8rouJkcWaXeQumQbzKsZFjJsB4i/6W2eJumwXRPbZzhqW6wg4OSND3d31Pl5UwQfpa85sJEC6uv4wul8kK0vJUXCX2tvC6fY1LRRRRS5WVoEatHAXav8iLJuhk0yG3Y+kJKze0qNVe9eo1ouDRpJ/kw0gSiWJPjUMW25N2WcfJBfRkukDH+UP9ZLI3xROXwKhOI5F90PcNJGfN/1JfgqhjjD02nYT2M8Ud1dpL0WdcWXwrj5MOIThyjE8dMTxwrJeoobbhu2vD+ipPShilt2PSUMQ3qa3m+mNHaoZPFthFQnCZT4bD0xAj0JDc7DWJCl3EQehfeZBlGANw/8yya44gyKod+TLFGjQA6jDgeoXYdAD3OZknbPB5wGNm8dfuBq5KzuPvRzs+zKV3ZVA2r1IxiQjlqsczgUWRox1X/4Pj6Mm3cNGtf/uzG3H1Zsx0w+KW93mcen790Q6xx56xxmcYYcsfslrH4l1hMYjGNWUwD55+4zLpc5r4LlRhNYjRNGc1S77glr1ljHRG7uQ12M8IJAUmLGUle6APVUU5VAzIKayRukos6thq0KnkeE32qHn+H7CkpLFGynahchUpRcdqt0K8l9pIq1DbT8oMjRUt0ZNOcaOmjG1OiJa12UbW2rNNUuvaImM4SRaD6tdIFVL+W6teakJ2cwq1GIMTg1mVw91ymROASgWtYybbMj29ZztZ8EVFN2y2QtzhFSu5WNU8NmDAwu7DGl5P4bD494ozVSjEcE/1qIIwOudgj18C9T+2beov4seFb/p2rXR21oizWHKNkagQpo3UH1P7gCFpT7ds0W2vej8bUrekjOshsNR7N/ma5spVIOa7dM7+mumOU78pmacx+Uq4r5boa57rWhAfEmtZlTQ9JwEShEoVqmgNr7HfXyYdNrFmGUm24wig7dhsE6ySZHMedTx19rmzlJPIxT2awJi3n0pvdf/Pc7xfevRd6aNszv4G9Xhcf8O7TA1QGhTKUpVD35bGkPKT4GibZi/0nL/2wRu/pn/DH1JutLZ3uABx5DDYb5KXo+WnJSiu7b4CDtB13sZjhMUnQdSzpZPFvYzf6Ds4bDnOMP4bm/CJKNbPRMWGCC+m7kYmpHoGsrcfgRcXwyDzB31gZ+vJrfvlw4Xz7cvH3j5++fKuS57nU5xb0qmb4MKbv3rqYJlbssr9+PX+/y0MtDKVijZhPcdnSksWkWVmp9NQNyhKtxz2BoOsvRL00qxfjuVa8zMrADdBVcYem+Jy8F5VgE+Gv2tLlmqM3cBbH7Kd6g4IJGsP/6j+C7Mfwv+E+JWz2xyAEF0myzDApBUU6Rwh0N/OYImWVFLZg8MsdR6y1qptzPju3eD4rPgM/m0RS2AxTGnvzKCD7d7snZc78KL7OPZ+7nTedRNdIJ3YuLodHyLWoZ11ZZH3qT2JsB7woaKwqDNFMAfMKRmeJig4e6VmiZB6yER55J9ntcOmeWqN6UTB5Oo7vDERNp5lpq6o8XiwFX36QnugN2x/8wH5wMQ6tdvH/dF11NJ4NqKM8y9uf6jOvbYXv04jB1tuBqnsMLuSn/GJp97lEJPrTSHnHDZ312Pqsx0NVUdEj2dYZHyYp7wZj/DGqvNSw+H061p1YK/vDS7MieEksvkmBUC8+m/7qwYCej6XqrDTiVwTx2W50ieWPZ0o35+66iQBb+LxueOfHoRuunMZlLRW6av8MP7xpdZ1LvqE9Y+DXvccG/wyoEiZHf8IVPH5Wy/Ouq8MaHSVWgFiBPS3oW1yfuw3jya51ZNdqFo4tjpf4BdHpVCUrSYaC4hmc1qbQk33kKPQ+HVEVRFUcuKYm1SiLRrQ2cZEam3H6qZrCKNidceGb6kaUpmis/JYYkk7rWnog33SPGWegRwN0Lfmox8edaAb/ijSKtkddMipHOecEQl4XhLTQ7GrNJcqFKJf9pFzKtyBiX47N8NUjYsq1hzgZ4mTMka6RV0j0DNEzx6O0oo/lVpZIGyJtqkibeK1BTp7A0WhXI1y/ugrSNzaFl0pvQbThhxQCfVV2SNmfbrkh0qFd4ps6VIKqSSYShUgUWqKzaxPrv0PETDsLUZdv0Ivk+NiGfYJJlbs6IXtC9seisimu11uzWqie4HBdOLxyYrbViyJEYt4YGlbMSWsck3MPCM90hYlzTe0MNi70a3MYmXRrX7ByA6UwnXTCzoSdacnOruvsEnuEoc0sRxssrRYRYep9ASilXgBha8LWx6a6SoyttnKEtbeJtZN9Xwu6c5PUBCDBpH4K5g8Xy/kcLv3oxZNHwkUtMLdCnq8JtZXd6RRhkwLt+EsP0QzMHiuhLRKGojanQnWiXhXqQxCdIDot/tm1waay268d7IbpqQn29cKmLH3R6eK87mUafaXrQmwAsQFHorEJCaC3frWz54tWYlz8irLXO6UQcAHMYP6ckE+gc48ziMSBYmLbwz3udR1JCQLV0HcH2yf92SC4P4bZ3r3pqpoOQsuElg8C12Ys6m6HnGus5VboMyMSCjHvjWeu2ikJTBKYPBaVVaPJjDWjUPJWceALk30RCPI5aXJwmxd/ewxm3mUMXhFF/Foc6icL8jUP98v2o9ND/khXdhSV1p503aQSCiUUSktydl1m1Xca05pYgpqH2ilEQBh2h8/60u/ShF0Jux66qibH0ymsFmHVTR4k58XOC0rciVDkeKScPAUN4MZH1599Az/tw28Tj8maIEdzeFoQ5itCVEVfuoSppDe7DFUbTX7Z5BJkJchKS3N2XWXpdxq2mlqFetBVJwqCr7uLCSp2b4KwBGGPQV1F73QWjKDsBqHsPQjdQXcLNmohdlDnwlS0gCZnd0EYe1MCJu0BrRDlDsDZtCebALOkMbsLZWtMvH5iCcYSjKVlObsut+97AWLL7UEzCJsVAwHY3UcEyh2b4CvB18NX1hx4zdougq5bga4uF7oEXMU0NAAh7935gxcGy0g1ZYf6omhu0K8IMAs96RJgHtXcbq5GCixRd+rGbsPKKHyTYF1u1QLXjBZNILpqcbuYyxYt3HkAakMnDr5781aiwLls0cBy6U/byDFe3rW43Z96TwxCT1YtzvplmThOyTjKm+jEEuktDTEexHjsJzehdg12u4gXbVC0QdEG1YSCU692qiInOp0YFoOD27mZrL6OT1rlhWgKKi9Kii5XXScva4MuopQqL8MlWj0KWIiVF0nLzaBBvqj2sZhfKRol8pTI08NXVtE39a5Tu3pfYp3HyQeTQ+vZo8ahivFS38AN9jj5UH0Lmu4x/qi+VIhtPFE58Kr/ZEs+ln8xGQlq5Zj/U3052vcx/jAYMFj5Mf6ovlSy9WPps8kzuOEfJx+oKmOX3Po0WZEOIxEiMHO5RdqAfr2Mg9C78CbLMPKfvc+cpTgOgl059Fek2TX96ZJsP8LZ3iSjwcSnfQRWz4ls/gT7gU+ys7j70c5PQC2E2VhLqrSA6FCiQ/eTDi0z5LtOiu66CalHVZXNBBFWKWHFbd8e0iMG/gORJESSHIvKih6WWb0GhAm7fSz+JQjdJYSOcKZArcVUOYkpHqt94gYIC7PnNwmwju01K5U8XxGjq7vTJUQnBdrxt66aqkDFFBP8JvhNC3R2bWD4d/olrBrmoR62LhEIvY61u/ijej8nxEyI+Ug0VnSwxJTR21kbhL8hyF2JflUT0gC7wP4fxeFyEp/Np0ccWK4UwysCWIO+dYlmj1wjNhc5mnqL+LGzY7A70Yo6s05ol9DufuJSU+O+24Hn3TAf9QCwqeQp0Cw6zSZ5H8PMNb0GAtAEoI9RfUVvTe1i7VA0sx9j9pPC0F3i8EkyY447nzr6oHTlzPIx/+dkBiucP77HJ+4epQnrZzCZRSOQapTf689BcdCRZW84sh090X3nI7vztJdbZ7m/D6DRYcnzM0sIe9EzfumyaAoQK0Q2O8jjfFp0cCTnxujtWPZWp9xIRgDfPPf7hXfvhR7YwVNpMr8BYlguFgG+1QcSQBhyK1uM4S3z96U75oF1mwz3FtfBfLZCizuPfFA3l2kVerOoYXfwBUwIfsTWAVf0ZE8eHgcKygI+o+TXkIWK0HoGaO4SDcTbQbF96L7URPos5vvfSnN2C8+aoqrCIKAtQAETd96P8UgVy5VaCBOhYB+DZQzY5BmQkBvBIAGmCBms1RzcO/ldQBT3qeplaJiKEo9fOO829Ca/C8ADpNcri+0z7XV9WLAXS1jKT96HMAw0u0L/sx9FOKViC0lbTiAfiIx/c/sfVl/dBALUVbAEE4ENMbzFxMzUAgRmXbDx/aVfZr3EwObs/c50O07ePqqBjYYthHEr9BlVyZum/XdldQYlsVChUXPBKPKrwHq7VtIRu3Kg4Jc8+xN2oqxYSX8FW3opvrUR//KPsBmoFSBtYRsakDxsCyqQt7qXsMIylqk4iDfW1Zf3XwaPcbyITn/44QGeuLyzJ8HTD1xb3k695x+egnnwAwwUPIIf/v3HH//v8NRyp9PUsKEBSIwbNyruYjFDFgE3T1vxTNgOQFlf+Fjd2Yu7inDZr6JEH3APlBrhZMQEbFeMNMqjl8i52Lh0F75WVkS1mbfOkmb4AVCwQu5t1Stob6zze/ZYxh5N/SmaumjhTfz7FZIibAOx+HvYYAqf3BU8AhwDywMjuVykM8sG9RagMqMYMvepHoquA468H8H2OAHzP7UYJwPGFNTSCnifmM/ba/FGYaKh4+RD9hJJyXIKVqJb29arjelUpT5VvMFoMA+JS1TCkBfcJYk4ZSNYSx+gwCzjNe82reY4idwQ3rWkxDM+H3QopYGYjASmKfqCSoQJH6U3WU1YPvkhDag8p/6jyx+h7IPUsH2+/qzqTtM+GD2Cuc/xcgFwQmlORoXJK9CBaSSBVk7nK6e+8rZZQpvV4w66Y/w0CVbGfjzzGlYJwpBQw1vd6a8eqOJzk/s7XZSVC688oEersWIf2/oqbdaLHVi9e7MpkgXhpFlCCtwmBNTtyEJ+6+QO/OcTBgoiDO1L99wuwLFOLk9oiGhkLeczD6G01w+9NduAiz8MZOJ2FgQLJMlE3gDSswgKViyDACxXjBZlAtjkwQ0RmeQfjSQbQwkZOuuNdNnXpCesyRPRF6QYZie5B6/HKlPLyaitW5vjG/YoxeKuuYQTHVTZMqct49rrPkrd6+mCwVUmWEWFZXqd479kQbBIVNUD6oaq80ZtpDb1ClpOmm1djCzfeHU4MH9HZdy62P+uwtjmnTfrcWU3NQZaHypn1rmysh1L7qm6KLW46isrgrkGU18nYNv9nO6ubmonvTik7MNLVbVisSYxWHmFGwVamcaN2U91UBSVbYw/1H9O1WycfhqV5BF4s/r21cR85U1XLaO6m1rfVuN3SNtrabreQokRDRRroWq+tTkp+bE32e71czgcWSfn82d3hgma4cPyyZvHDKDa1nv4CiM0CxjV6T/nJ9Y/M3eeWNZb68zqJ/3pc25Z5IghTQ+tWH1RkwV6YWecjv5fNE32xUhEe+j66RqUh9X/y0mpcu7NemusrybLr9exgS41ziWGudIoDzP+rsbfyVtYUGDmaHMolnW3z+arEfI06E+r1qcmlWiYd24z3rGUEHmqCGW9DzBk5s8ns+XUkyPCuMWwpXKLt96y5BrUdkUbgJxeWDN3MDHfWchmEUQ+xw7rJTv1pkvG/tiKsXG5WP8GI5e7Pxr2tNeV7eajnnHi0rAUG6xl3jJaLye4qb0IQaylGJJPZdoBmwNThwHTwVDZBJp7S58Mljwhh4s1D0LkrXlO+iy5xTXIV95T/HZo55n+TGpfMtmVGZW15ixlDM/nPmb5+//yDGctGWu6zuPZatB8DBIAT+rpNkD1P4WLyWdxuwLay4HNktalJKqcUVNmVmcFpesa36HYL9mM6io6QWHQ0rttuUS83rDJMs1mYacNlD0kX8C97EFZEeceJv8xJ9msjS62brqnKPgQmM6BkDFWFLbxx/8eDE0ykQvMytosPHhzNBneulNxerFa/flfUQEcttEmKyh5SPoXXTKpSHzgd2spIn7Rz3DNoJ+psif8hc/8zaO+JrWVh0LGfb6Q++qL5ELKedKifHGnmXayC1PMSs7setnshLyO9YqGEO9e3qVeVvpE2+FphrJVHObTRgYFlyu9Pzu2nP/FGWJ0wH7Bd7OKOpDYTd63UktZunfXngAxrbxauWwL1JeWSntUsf8MCwkj7XOWW+Yrq3KVeUINJiKzDw0C9BghzOx9LB8ZdlA3MsrOtf40sh6Dl9MKQPG34EWZRCpf88uHC+fbl4u/f/z05Vs24TlNsz6Xeto2NUE9chjOd299Yg2ztF+/nr/fpVFWjkSd1m0+qarwmCwVjR+TCqvYkCy8euE7kGlJKniV0PJJmsrLc6ZSNkoGac/S5QpjiTIfs59FkwMiHcP/xT+AtMbw/6jCJCkVIeO0d6IIw4I4obWsw8xarOrVGpxsq1u9wlRkRYpyrl6t51cfLs6uzr/8bDYBAulBZ+r2sLo7Z5++nf3jUpvMiNsh6xI4UOnnwX0Y/Au2wKtw6fFNjuc765ZOT7UQTs0Jo0ZVCBROxP6+tvz6OZZtXp9umfWy0UoZ7XId2pTJIAXdTCrj6xTnaJPr0zLfp23Oz6bWQs2EQVoAG84ePEATTgtRsxDfWF//n+U/LULYgTCqcmpNHr3Jdx6InHs+ex1HFX15cSPLneDLSvMYRL/KtfoAI8MEvIeLX96lp2uyIGsdrncOXyZ6KHhfiYyX/zJWJyS0fJhEMps8TEvAdZZc103+X2mEquvcuvb5dQ3KwVQk1Rkm1jlq5lAbx2DvSudezq1T++VUGxzj76legZj5S6r3Jx9+W6D9mD9Y98EyjB+Vi5S/Ol6ZRzCyHqDT/d+F1qskMbQdwaz/0T9R5MqZ58sZ58yZ583pww/pfFUV91FPXaNkk2azCP5MON2BSTSpydIzWFCNk9+MEuAMkuCME+FMQsDdJMS1TorbHXXedVU2UuNq+5GNrJbksZULvnUCW/1JiDzwlLSzIBw7eTLA3exjQpfprFSNqe4MVS6EA8m2rZG31WueiZVmNo312UHllaQyAeRmMdbK4k5yMaeSw4TNEg3aD3hrw+lpk4Ky20hxJGkGkDZ3cPcrXOUjx703Jf9ZScEXUHSsizR1F1gS1Sq7pweoFovO3K3YTfavkVQK5gkWHJpBXl2C1WqdTPCFLVEplckCrThe//YZnuXa0OCFN/OeXW49k8awfFYYSn/gYo3sXo8HOpJDwMT12JkzHADY6mSisWLIzIuDeZJ3Eg5PK1+sdVBXnHswjxPcYbAOjyaydb8E5VpzDEkNvI/s6/Vl/CmnmOlTCHG9PPrgz2MMJ7vqpiwIv/DmU9xvxupie/hdUYuvebduRors2icvWMbj/zNCBeKbWFSSX/nGesf4CjCOL17/mVdMmVqsIBHM4Sx4wFJabjjnjgkvq+KHuTZYUa1HN4IN0ZtbqUyZxvOsVV7mJVzOsSE7b5dn3nyA4hha47H1v4rGCbrxAHMt+qG2T/cn77AXrCYxW0r93/mHP/rKrq3SojBY9etE2ebJX79eWd8+WGcXH6zLq/NPn6xvZ+dX5z//xAvqxaDsuBxiz7b+ESxZ1aZkgS9g60TvQtNwUvDKTnt0yxZAMhnrvrHOr/sNFgcz7DXNTlne7zSwQNAerko3XDHrg54J0y/seBSgZNIZxTI8c+8Zq51NJsvQPulV54om1i1bwwXzjWVL+nPwAi1Dr5mViJdIdFm3TNFv2RC5Hie5zJi5zEYgNfHoPqM5gQGBnQ996ObU8n6beIt1bZoHL464ikzVb5T+/OXqwykvePPC1JD5fdDouiEhcqE67AJ4zrOXNcfB8uExnRo2Me4MC8WtNIr/BPY9gg9SI09BiNuH54bpcso9NREG9vZxJd7IBU8l84prPGHzh2s0eoHOBC/819V6TGtZcMvCZd1Lo92O48/BCjoDLDAn2StWb875NVrXB1sXpxuLv66rLErXDYZWPvLgxnH4Fh7mz73pzfrR7hIGHPr/gnvYw5GLNWb48GZn3UJkn6Wfbwph+3x3c0/WjNNoINJ2gjowyAhw1MsV4jutESBZ3/xrFMwTr0neXVBg8Nt6uOKadQ4T3mljSDQayI1Ijg7LqoAbxF9YDbg++7IvX8UZpP5j8IJFypOr5fSgdRvX7LIbObGW/V2VWZVkukQiNUL5WhTvo+o9JzG/ot2HIAAvwGE16e+W92z0uL8/ubEt6nleBf8VyQks2cURLReowDbz2dOUf5tNrJimoc5jFH3FkYKAris48/W45XyyUa27FHktN4XqY+1Eo3szIiuoTMqSSCVScAAGSiALQ0lOKp68TktSPFo3ecPC6mUpuRtZvjzZNx9lQD+F1YdlIapR7q9nKPi0fOxNDVugCAgn6cZMZqc6lRBVcRN1yLEl7JwFRcwidCfY32jhKlYVx74M+d+f/J44O7k08z8G/dyffPDWhieK0nvwEN7aiRgSIjEJD5yo6gLiOQ9wE9sZ74JnLDgI+6aXQBWOyJADQArochL6C0WhxAW71uFVDP0JS8YqPgwwjDcb66V0Bf96n/Ai+93Xy6svnz9c5BBo0etlEx560XImEvtTkCBmVekD1l72rOlhFcpurAkb0AalRlhvLRZAs94Fi1W1dnSoIeZa0ommaLSFW/6MsmhcAfkqTRSD21iUJFKA+kCDgbL94oaR996fxOVF0eVOXfM3hPs35bXPuQMnv7viDErKpetegysLnPV5t5jnI/ewRPog9+xYRBM3pTE/5IT5hQwDgz3XPIJt7fzK3o56f1t0/0qdt9y+ntvRFa+kihLge+bnqTy1el5aSw+trneWzExadzsRPFsGY9D99MUdwfJZiV1NTq06rShR2cCHk8/7zRXUP7Uyr7E98E45i7sfk1faRtKkMA685JZMhEWuBlZ1A09AkojF3XLMpP1WzMdeO2W77QVzAXP+xwv5e9PWLQzoaRHg+QWIMW4P0Sm+W8E6YcFd6X2tu9h5/rM7Wzy6f3bmoIa/RmzhZMWh9j+++/PpuKId1b6Qsy1VTQjDoveBjN56XeuUVJNdXU+77L1fjSLqG+BMdOZFzPGawC78raShIPjurzvAfy3JP1ksnKQKfHqT/GXJrcv4cVzucrJ8g/U5Fzbeoq2pU9jw5LvsOODOr8PUs6RKQ4l/muy0OLf1Oi7dad5/fCld0UCjrsfrhHAnxFVeewiKFpoNRdFQ7SFpvmbLhZevx2AjN7pXwWUcYlBKc5PwB8biX7Mbh6rLskAljTVoYpPXKLqbtY3M/jXfGreqArfkYp4aRj73OEZWKRNk43B1ui9UQpzuGMdCGShmPo3yrKUxqAiIlEN0ZYylbJPQALSC7usvWbsJI8PqN3Ko8MVLw5a3iZ5Hj5gDdSvHKjHeywLbmsYmQRh6k3i2WodeWRBSiBnjvSJ+zEKNPAivaQuLmqXjtsu4BNWMlh3DmdcCXSoCF8BA0Xwuv4gFIPN3v0v6zlLtirq4HlvkxaL5AfZXQdBI0/QZ9H0t3VtF526tO2/i8rC8Hyna4md2cR/vFuPkt9Iews/vgge9O/sZnwqj8yZLBQH0xnqCZ/owm1bk40d37gXLaLayVQGRijlSL1VBdrAlVZbAYrDE9Qunn82g6o9MWTMWvVYogqrK2Wf3OzIGWGk60WoWCL+VsiGEVESmJchMOrRt3ZIUwcfDacLgZc6q6vFwvlBo+BMOahnOWXhd0Uwm+8D6jglgbsiOcIYmgmU48bCJGQiEGQU/1tVee/IfHvEIO9S3JcuOCpdzlk4T3IOP/xSEK5aKEYSRN+IPQtysaOk+DJ5geD7LRk1UmCfT4OTzNxdCsevYJeuJf1L4pIoZU6YGKpral/1cKADjoJHJ5r7UcYUD6uDkC3aHvRaVmVUxtRH+veiT/Tc3YjnFA0H1a0bQWK02pFo59eKBFjPt6ljD6mlZZ5pWom114kYMF1RwqkZamFV1Wx+cKXf8aurrMmIRln7pewWDqqOQtX8Xe+/ZXRDChqO/DLcIh/enXEKmYbpachZCGFXek316uJiIPrPJvuTdrzjmeNg+qie848J8hoJX7+/Vrsa6bGB5tDsDCx0ZhhzklSjkl3RBKl5XPAr05OvcYy/UeNNkL2JejYgOFDJx2LpoE8S5YIf2biOIw26pEcMR1+dDOF2x2SYsNj/ReNTrkr1OWGs2vL7BAaJ6sroxSd2anDYkpRuQ0SUkdG3yuQHprDCq1SRzU3K5Hqms6Jo5idyWPG5GGg+1Rd1qk8O1SOEKMrg7InhTJHCBAN4M51iLa9RyjCXcoo5TzL9R0wGH2AV3WMoZNuAKu+II6/ODptxgIvrlfOZ/95jMSpi9EYr//Re8J9eKgxPnsBf3zJlFxiPmGuJbbkIhTtgbJ4w+XJOF/JIod2OOQgTYCNpy57EXk13YPbE5/krVi3h1DgvG5GvIBMHUuoeh3LlJRRokxbCiTPGFqBHrJXJt+WaYPsAd4VNKPCXj5qdNiyGsVRn+rnhBLK+CTWjQJhSoMf2ZUp86byb/4mmGP1Oxnd0wnR2wnJ0wnN2wm62YzQpWMzcjBTazisncCGGmJcqGhffT65INZURDGcnANbyMXzDjFrrhFepyCi35BOPjMHq9NvxBFcTOIMKuETZrvAiwL2HSkxoL+5EsKfe4BtzO3rZHiZNyxyl9ktInKX2yXvqkvH4oiZKSKCmJkpIoKYmSkigpiZKSKCmJkpIot5xEaeCOUiolpVJSKiWlUlIqJaVSUipl56mU8g5MCZWUUPlKCZWqgETXQZ9M7KAQ+5EObeoqDFQ8B4piQR3GgjQzRmEhCgsdQlhIIgi2ExvSrCcKE1GYiMJEFCaiMBGFiShMRGEiChNRmGjLYaJ6nilFjChiRBEjihhRxIgiRhQx6jxipNmMKXhEwaMDDh7pgg2KONLqKniXHKhVIF93oGgHV207WVi297SIV+yeD/hJihlVXHl4dTqUk0d1O2oQ2lS3ozkhTXU7qG4H1e2guh1Ut4Pqdmyiboepd0N1PKiOx2HU8VBqPNX1KP22m7oeFdCxe3iumOgqcP7hNw5wCKTvMUjPTSKBdQLrBNYJrBNYJ7BOYJ3A+oGA9Wovh0A7gfZDBO05zSfwfujgPTfhChAP3uqnYP4Abc+hCx+9ePK4H6diqHpefFPz+AC9QiyE4wnHE44nHE84nnA84XjC8fuL482cG4LvBN8PBL4rFJ5Q+wGidsU8V4J1fjLGTp2tsYFI+y4XTVLNB5VMopJJdJJGzWpJqoVEtZKaslsGLFdjtqsF61VCMZmzYG3ZsGasmEHXqVYS1UqiWklUK8lqRX9W0qAGdGgVLVqOqKhWEtVKolpJSr6x1C+lSklUKWkftneqlESVkqhSUoeaVqJtqcipUlLrSkmqrZjqJBlNouHUUp2kXYsDiYhCIRD0kxd/ewxmHqqGtx/pmpku1zhRQzzq8BI1MwKhDE3K0KQMTcrQpAxNytCkDE3K0NzbDM0qr4ZSMyk18zBSMzOaTjmZW8jJrMOOdQHGMzNcBOEfXX/2DQzOh8SyUM2j/UDehYkj9E3om9A3oW9C34S+CX0T+t5b9G3i2RACJwR+GAi8oO2EwreAwrccES9Msh6Ii+knGL5fMFxMG4FwAuEEwgmEEwgnEE4gnED43oNwvV9DEJwg+GFBcKHrBMAPF4CLuU3g939OZtB/juVyePybcN3XczSZRTULE4kmCki8AbDWovbkIckxx68DsROgsxmQnYyR0DWh66NF17sJmN9Yn/z5d2u54ABA4cmxl6vQMxOySJGfH0utJL4OXu3PhbtjPfsAXtLphksGw1u4BCxaig2lNkBXF+4Dvrl5m4VSgFK4+w8+3sMj88LsXyM7b8zttRsNQ08/b54dSNA6PnUW2c4avjv2gxdLC0/stukNMlCtTzbwRtoRDkkbRDoQ6fBapENe/OkmVEo7JBftNfHAhbxF4oEZqM3xDiWuHhEORDgcBuGQKDkxDR0zDXXy7fPAuWvKIWm/GOp/784fPFj9fADRTtU+1t6S63SLQ4p2uBZybpBUBZmqIFMV5HpVkHNLiOofN6X2DCi+xlRfC8qvhF8zpwDbUoHNKEGDrlP9Y6p/TPWPqf6x1SqzqpLsNCA9q8jPcjBF9Y+p/jHVP+aUoplHSpWPqfLxPmzsVPmYKh9T5eMONa1E21KRU+XjtpWPc5sw1Tw2mj7DSaWax6+eYJqPHBSCPpcxgM0LcLnDyH/2PntR5D54+xH6UXa9RvVjzf35fNUdjgspR0DRIYoOUXSoXnRIuZAoRkQxIooRUYyIYkQUI6IYEcWIKEZEMaItx4jq+KUUKaJIEUWKKFJEkSKKFFGkqPNIkXIrpngRxYs2Gy9qFr3oOoykDjQUgklY4bPLWNL2TtBU9bxGKEl9+2tWPtlkcVHVaKkGSg3ym2qgNCevqcIoVRilCqNU7IMqjFKF0U1U+jB0bqjqB1X9OIyqHyqFpwogpd9u+MjNMjTZNbJXPasI7AESgnu3nMRn82nnGaNX6315G1C/ciw1cL9BW3uUTlo5GkotpdTSQ0gtlZDAdvJLK1cW5ZpSrinlmlKuKeWaUq4p5ZpSrinlmlKu6ZZzTZv6qJR3SnmnlHdKeaeUd0p5p5R32nneaeW2TDmolIP6SjmoxuGPrqNW1ZEKmKZe703Jf9ZFAkyZ12W5GATBTIaym3pvrK8R9OVulZzWZH3z3O/rpnyEd0/eHOYJHFHm9LkT8BgTow4AcMpYfmgJ8fHbZ3ika0NnwCSLbI7JzIcGIrvXY8cAJiYi8yApbDNIzyiRL4AZzcXwGDgu4nrYeMLQn3o3mgjen6RgHjTg3s0KTNE78f31tcaCPPFJscXk3IxyDZyhF4st3Kwf5nKz5vDO4s/rzBKzYYnZ4iJb2MCbQhxQcXtl59I2mOFLA4qgcFJIEH47zT8MvCv5sbJvXODEjG2t3IlR0n7+SAmx0BMgn0zUoHB5FqtXPp2tQtAha4G/OV4RyifTxP4kuZfFObpcRbH3JGaqaA8VfqnNGuUbwNf59zkAOtUOICYQTajUzT/+wzrRbQcnVyJnaxktQVQrDtLYsnZhrXgL+GoOcoOvEtkkTxlZL4/+5DEB79FysWADwnvTok7/nGsfbZ1ceh4DpDP/yY8jC5OuTq3HOF5Epz/8kDYx9Z7xlwdwx9FDfPuwhDUa8b+/5bf+cFKZlcTttxAtzq49XT4tFG7A7+qkKL4D909NFEasn6vgvT8pCYllFAbjKMIzMc29+EOTfik0+68uaG1KBIDmpqzAaT7Dxo982EUQxg7Si0YZu6NKszEWqV6smxLtWgwwkkrR6t2iP3rl11WlVrVWu9TZ6lI6SaMN9Sy/m0YA1abLmddqR+XxYWlvMc2ZyVRZs/67XnpN+fW544GVF8P3LBxrfxAfiok7Qjz5UaBv57wHL/YKPuDRx/jv/w/mElgF0T0tghi8mFVVTErqknSXfb7+vLsuQVsPoKc2ZUkwxVh7ckYudqPvqSPx4MUY9ykuKuFzXooozxXcpDGBSSpFaZCH45rQu0+D/k761cjk/RG+kHLJJoNUaIk2jpMPXW+UKLXzaaf2Cpu08Qeodhubxcmms+k0kQISTv6cdwY3yThg/giIEDBQ7NqydWLfqCwRanNk/wQw/bO4CpQmO5hB8a5Hni1uX51d/t25fPe3D++/fvqwnh7bjwLer8FQfglG8qO5PAoKCn6YFw6GthMzTRRaNBwJxRgOVK/gZNVFMiBj6XP2okQk4+SDspdm6lRUpRZqJAST1Yk/evr9iyfu19+9Gm9ZmZc5K7agXd/dNriVpH8K2F4Xle4y4po17mK6NgvcaTSQG5F3i05310ICCGxGfeniPliapJenuuWWh43ZGRPCt6UbikbTnfluNBYPus704IadVd1nV/QVW8d3b1V6I/xdddtj8KJJeSqX3tmnb2f/uFTeCLIrH8GLu4r6I+ujO4u8of7txvIO/PLhwjm/+nBxdnX+5ecm/QBLew7rgm0e/ZJuKJMP8i9S9nKGxXl059OZt1aJ++V8EgfBLLIB3Me+m0v7LGwAwq4VdoDsczOZjWKwbHQn/C9X+IeTYc0dYpjfAeQI/qSQsprQNOPM0EdKfgVtzLjKHUsGa/2b1RdES7/svVXZjI3lX7KXyZZqnPFGS/YXnl+xxf2FdgLaCWgnOISdADUngQR6tXl59OZrfcmvNuQZAEI+LXhWQ/JbjgvDNlhs6r9giYj4VDrgtAs31328sH+jPMlZtvEpKaSrnaHCqUYoOUWwhnQKj/oWxTHAkSiU2Aj91NgzDPeNzfgAYu+p8AGMhlzbUSAfYO0DSHmV5AiQI0COADkC5AiQI7BFR0CYdnIFXp0OSGZie34AscjkMpDLcGQug8jfVboN66vaugy13YVebV+hxE8o9RE26R8YbZOd7iK9N9bKXdyfWt4ct8be/wCEHQy7TIoZAA=="); + reboot_native.importPy("tests.reboot.greeter_rbt", "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"); } importPys(); diff --git a/tests/reboot/greeter_rbt.golden.py b/tests/reboot/greeter_rbt.golden.py index 52eac3f55..7120ca11d 100755 --- a/tests/reboot/greeter_rbt.golden.py +++ b/tests/reboot/greeter_rbt.golden.py @@ -21729,24 +21729,32 @@ async def Greet( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Greet', request=GreeterGreetRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -21758,13 +21766,18 @@ async def Greet( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = tests.reboot.greeter_pb2.GreetResponse() - __response__.ParseFromString(__query_response__.response) - yield GreeterGreetResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = tests.reboot.greeter_pb2.GreetResponse() + __response__.ParseFromString(__query_response__.response) + yield GreeterGreetResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -21791,6 +21804,13 @@ async def Greet( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -21900,24 +21920,32 @@ async def TryToConstructContext( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='TryToConstructContext', request=GreeterTryToConstructContextRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -21929,13 +21957,18 @@ async def TryToConstructContext( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = google.protobuf.empty_pb2.Empty() - __response__.ParseFromString(__query_response__.response) - yield GreeterTryToConstructContextResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = google.protobuf.empty_pb2.Empty() + __response__.ParseFromString(__query_response__.response) + yield GreeterTryToConstructContextResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -21962,6 +21995,13 @@ async def TryToConstructContext( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22071,24 +22111,32 @@ async def TryToConstructExternalContext( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='TryToConstructExternalContext', request=GreeterTryToConstructExternalContextRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22100,13 +22148,18 @@ async def TryToConstructExternalContext( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = google.protobuf.empty_pb2.Empty() - __response__.ParseFromString(__query_response__.response) - yield GreeterTryToConstructExternalContextResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = google.protobuf.empty_pb2.Empty() + __response__.ParseFromString(__query_response__.response) + yield GreeterTryToConstructExternalContextResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22133,6 +22186,13 @@ async def TryToConstructExternalContext( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22248,24 +22308,32 @@ async def TestLongRunningFetch( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='TestLongRunningFetch', request=GreeterTestLongRunningFetchRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22277,13 +22345,18 @@ async def TestLongRunningFetch( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = google.protobuf.empty_pb2.Empty() - __response__.ParseFromString(__query_response__.response) - yield GreeterTestLongRunningFetchResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = google.protobuf.empty_pb2.Empty() + __response__.ParseFromString(__query_response__.response) + yield GreeterTestLongRunningFetchResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22310,6 +22383,13 @@ async def TestLongRunningFetch( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22419,24 +22499,32 @@ async def GetWholeState( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='GetWholeState', request=GreeterGetWholeStateRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22448,13 +22536,18 @@ async def GetWholeState( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = tests.reboot.greeter_pb2.Greeter() - __response__.ParseFromString(__query_response__.response) - yield GreeterGetWholeStateResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = tests.reboot.greeter_pb2.Greeter() + __response__.ParseFromString(__query_response__.response) + yield GreeterGetWholeStateResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22481,6 +22574,13 @@ async def GetWholeState( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22590,24 +22690,32 @@ async def FailWithException( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='FailWithException', request=GreeterFailWithExceptionRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22619,13 +22727,18 @@ async def FailWithException( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = google.protobuf.empty_pb2.Empty() - __response__.ParseFromString(__query_response__.response) - yield GreeterFailWithExceptionResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = google.protobuf.empty_pb2.Empty() + __response__.ParseFromString(__query_response__.response) + yield GreeterFailWithExceptionResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22652,6 +22765,13 @@ async def FailWithException( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22761,24 +22881,32 @@ async def FailWithAborted( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='FailWithAborted', request=GreeterFailWithAbortedRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22790,13 +22918,18 @@ async def FailWithAborted( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = google.protobuf.empty_pb2.Empty() - __response__.ParseFromString(__query_response__.response) - yield GreeterFailWithAbortedResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = google.protobuf.empty_pb2.Empty() + __response__.ParseFromString(__query_response__.response) + yield GreeterFailWithAbortedResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22823,6 +22956,13 @@ async def FailWithAborted( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -22932,24 +23072,32 @@ async def ReadRecursiveMessage( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('tests.reboot.Greeter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='ReadRecursiveMessage', request=GreeterReadRecursiveMessageRequestToProto( __request__ ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -22961,13 +23109,18 @@ async def ReadRecursiveMessage( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = tests.reboot.greeter_pb2.ReadRecursiveMessageResponse() - __response__.ParseFromString(__query_response__.response) - yield GreeterReadRecursiveMessageResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = tests.reboot.greeter_pb2.ReadRecursiveMessageResponse() + __response__.ParseFromString(__query_response__.response) + yield GreeterReadRecursiveMessageResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -22994,6 +23147,13 @@ async def ReadRecursiveMessage( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in diff --git a/tests/reboot/greeter_rbt_react.golden.js b/tests/reboot/greeter_rbt_react.golden.js index af09b2f6d..324349e04 100755 --- a/tests/reboot/greeter_rbt_react.golden.js +++ b/tests/reboot/greeter_rbt_react.golden.js @@ -1878,10 +1878,11 @@ class GreeterInstance { } }); } - async read(method, serializedRequest, bearerToken, responseType, reader) { + async read(method, serializedRequest, bearerToken, warnOnFlowControl, responseType, reader) { const queryRequest = new reboot_api.react_pb.QueryRequest({ method, request: serializedRequest, + clientContinuesQuery: true, ...(bearerToken !== undefined && { bearerToken } || {}), }); let expecteds = []; @@ -1936,6 +1937,7 @@ class GreeterInstance { endpoint: `${this.url}/__/reboot/rpc/${this.stateRef}`, request: queryRequest, signal: reader.abortController.signal, + warnOnFlowControl, }); for await (const queryResponse of queryResponses) { if (!loaded) { @@ -1981,17 +1983,40 @@ class GreeterInstance { // orphans list with a length greater than 0. In this case, we don't // want to skip checking the expecteds list just because we have // already checked the orphans list. - if (expecteds.length > 0 && - queryResponse.idempotencyKeys.includes(expecteds[0].idempotencyKey)) { - await expecteds[0].observed(() => { + // + // A single query response can report the idempotency keys of + // several mutations at once, because the backend aggregates the + // keys of every state it skipped over on its way to the state this + // response reflects. Two mutations may also share an idempotency + // key. So observe _every_ mutation whose key this response + // reports, not just the oldest one. + // Both of these are looked up by set rather than scanned: + // a response reports the keys of every state the backend + // skipped, so the further behind a client falls the longer + // both of these lists get. + const reportedKeys = new Set(queryResponse.idempotencyKeys); + const observeds = expecteds.filter(expected => reportedKeys.has(expected.idempotencyKey)); + if (observeds.length > 0) { + const observedSet = new Set(observeds); + expecteds = expecteds.filter(expected => !observedSet.has(expected)); + // The one response we have in hand is the response for + // every one of these mutations, so publish it once, on + // the last of them, rather than handing every listener + // and the offline cache the same response N times. This + // is the same shape as the `orphans` loop above, and it + // matters more now that a response can report the keys + // of every state the backend skipped. + for (let i = 0; i < observeds.length - 1; i++) { + observeds[i].observed(() => { }); + } + await observeds[observeds.length - 1].observed(() => { if (response !== undefined) { reader.setResponse(response); } - expecteds.shift(); }); } // If we don't have any orphans to observe and we don't have any expecteds to observe, - // or at least, the first expecteds _is not observed_ by this response, then go ahead and + // or at least, none of the expecteds _is observed_ by this response, then go ahead and // pass on the response because it might contain new data that should get shown to the // user (e.g., in a chat room this could be a new message from a different user). else if (response !== undefined && !haveOrphans) { @@ -2133,7 +2158,7 @@ class GreeterInstance { unuseCreate(id) { delete this.useCreateSetPendings[id]; } - startGreet(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startGreet(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useGreetReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -2212,7 +2237,7 @@ class GreeterInstance { }); this.useGreetReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("Greet", serializedRequest, bearerToken, greeter_pb.GreetResponse, reader); + this.read("Greet", serializedRequest, bearerToken, warnOnFlowControl, greeter_pb.GreetResponse, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -2234,12 +2259,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useGreet(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useGreet(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startGreet(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startGreet(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -2475,7 +2500,7 @@ class GreeterInstance { unuseTransactionSetAdjective(id) { delete this.useTransactionSetAdjectiveSetPendings[id]; } - startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useTryToConstructContextReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -2554,7 +2579,7 @@ class GreeterInstance { }); this.useTryToConstructContextReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("TryToConstructContext", serializedRequest, bearerToken, Empty, reader); + this.read("TryToConstructContext", serializedRequest, bearerToken, warnOnFlowControl, Empty, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -2576,12 +2601,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useTryToConstructContext(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useTryToConstructContext(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -2621,7 +2646,7 @@ class GreeterInstance { }, 3000); } } - startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useTryToConstructExternalContextReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -2700,7 +2725,7 @@ class GreeterInstance { }); this.useTryToConstructExternalContextReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("TryToConstructExternalContext", serializedRequest, bearerToken, Empty, reader); + this.read("TryToConstructExternalContext", serializedRequest, bearerToken, warnOnFlowControl, Empty, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -2722,12 +2747,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useTryToConstructExternalContext(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useTryToConstructExternalContext(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -2767,7 +2792,7 @@ class GreeterInstance { }, 3000); } } - startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useTestLongRunningFetchReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -2846,7 +2871,7 @@ class GreeterInstance { }); this.useTestLongRunningFetchReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("TestLongRunningFetch", serializedRequest, bearerToken, Empty, reader); + this.read("TestLongRunningFetch", serializedRequest, bearerToken, warnOnFlowControl, Empty, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -2868,12 +2893,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useTestLongRunningFetch(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useTestLongRunningFetch(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -3011,7 +3036,7 @@ class GreeterInstance { unuseTestLongRunningWriter(id) { delete this.useTestLongRunningWriterSetPendings[id]; } - startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useGetWholeStateReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -3090,7 +3115,7 @@ class GreeterInstance { }); this.useGetWholeStateReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("GetWholeState", serializedRequest, bearerToken, GreeterProto, reader); + this.read("GetWholeState", serializedRequest, bearerToken, warnOnFlowControl, GreeterProto, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -3112,12 +3137,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useGetWholeState(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useGetWholeState(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -3157,7 +3182,7 @@ class GreeterInstance { }, 3000); } } - startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useFailWithExceptionReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -3236,7 +3261,7 @@ class GreeterInstance { }); this.useFailWithExceptionReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("FailWithException", serializedRequest, bearerToken, Empty, reader); + this.read("FailWithException", serializedRequest, bearerToken, warnOnFlowControl, Empty, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -3258,12 +3283,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useFailWithException(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useFailWithException(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -3303,7 +3328,7 @@ class GreeterInstance { }, 3000); } } - startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useFailWithAbortedReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -3382,7 +3407,7 @@ class GreeterInstance { }); this.useFailWithAbortedReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("FailWithAborted", serializedRequest, bearerToken, Empty, reader); + this.read("FailWithAborted", serializedRequest, bearerToken, warnOnFlowControl, Empty, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -3404,12 +3429,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useFailWithAborted(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useFailWithAborted(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -3645,7 +3670,7 @@ class GreeterInstance { unuseStoreRecursiveMessage(id) { delete this.useStoreRecursiveMessageSetPendings[id]; } - startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey) { + startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey) { var _a; let reader = this.useReadRecursiveMessageReaders[requestBearerTokenHash]; if (reader === undefined) { @@ -3724,7 +3749,7 @@ class GreeterInstance { }); this.useReadRecursiveMessageReaders[requestBearerTokenHash] = reader; // Start fetching from the server. - this.read("ReadRecursiveMessage", serializedRequest, bearerToken, greeter_pb.ReadRecursiveMessageResponse, reader); + this.read("ReadRecursiveMessage", serializedRequest, bearerToken, warnOnFlowControl, greeter_pb.ReadRecursiveMessageResponse, reader); // Check if there is a cached result if applicable. if (offlineCacheEnabled) { reboot_api.assert(cacheKey !== null); @@ -3746,12 +3771,12 @@ class GreeterInstance { reboot_api.assert(reader !== undefined); return reader; } - useReadRecursiveMessage(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { + useReadRecursiveMessage(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, setResponse, setIsLoading, setStatus) { // We need to call start here because with strict mode the // `useEffect` that calls this method will also call "unuse" // which will mean the next time the `useEffect` calls here // we'll create a new reader in start. - const reader = this.startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + const reader = this.startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); reboot_api.assert(reader !== undefined); // Indicate that the reader has properly been used so that we don't // clean it up prematurely. @@ -4005,7 +4030,8 @@ export function useGreeter({ id: providedId } = {}) { return create; } const create = useCreate(); - function useGreet(partialRequest = {}, options = { suspense: false }) { + function useGreet(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterGreetRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -4046,7 +4072,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startGreet(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startGreet(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterGreetResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterGreetAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -4063,7 +4093,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useGreet(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useGreet(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterGreetResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -4382,7 +4412,8 @@ export function useGreeter({ id: providedId } = {}) { return transactionSetAdjective; } const transactionSetAdjective = useTransactionSetAdjective(); - function useTryToConstructContext(partialRequest = {}, options = { suspense: false }) { + function useTryToConstructContext(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterTryToConstructContextRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -4423,7 +4454,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startTryToConstructContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterTryToConstructContextResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterTryToConstructContextAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -4440,7 +4475,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useTryToConstructContext(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useTryToConstructContext(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterTryToConstructContextResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -4669,7 +4704,8 @@ export function useGreeter({ id: providedId } = {}) { }; } } - function useTryToConstructExternalContext(partialRequest = {}, options = { suspense: false }) { + function useTryToConstructExternalContext(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterTryToConstructExternalContextRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -4710,7 +4746,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startTryToConstructExternalContext(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterTryToConstructExternalContextResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterTryToConstructExternalContextAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -4727,7 +4767,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useTryToConstructExternalContext(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useTryToConstructExternalContext(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterTryToConstructExternalContextResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -4956,7 +4996,8 @@ export function useGreeter({ id: providedId } = {}) { }; } } - function useTestLongRunningFetch(partialRequest = {}, options = { suspense: false }) { + function useTestLongRunningFetch(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterTestLongRunningFetchRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -4997,7 +5038,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startTestLongRunningFetch(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterTestLongRunningFetchResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterTestLongRunningFetchAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -5014,7 +5059,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useTestLongRunningFetch(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useTestLongRunningFetch(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterTestLongRunningFetchResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -5288,7 +5333,8 @@ export function useGreeter({ id: providedId } = {}) { return testLongRunningWriter; } const testLongRunningWriter = useTestLongRunningWriter(); - function useGetWholeState(partialRequest = {}, options = { suspense: false }) { + function useGetWholeState(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterGetWholeStateRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -5329,7 +5375,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startGetWholeState(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterGetWholeStateResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterGetWholeStateAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -5346,7 +5396,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useGetWholeState(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useGetWholeState(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterGetWholeStateResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -5575,7 +5625,8 @@ export function useGreeter({ id: providedId } = {}) { }; } } - function useFailWithException(partialRequest = {}, options = { suspense: false }) { + function useFailWithException(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterFailWithExceptionRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -5616,7 +5667,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startFailWithException(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterFailWithExceptionResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterFailWithExceptionAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -5633,7 +5688,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useFailWithException(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useFailWithException(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterFailWithExceptionResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -5862,7 +5917,8 @@ export function useGreeter({ id: providedId } = {}) { }; } } - function useFailWithAborted(partialRequest = {}, options = { suspense: false }) { + function useFailWithAborted(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterFailWithAbortedRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -5903,7 +5959,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startFailWithAborted(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterFailWithAbortedResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterFailWithAbortedAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -5920,7 +5980,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useFailWithAborted(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useFailWithAborted(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterFailWithAbortedResponseFromProtobufShape(response)); }, setIsLoading, (status) => { @@ -6239,7 +6299,8 @@ export function useGreeter({ id: providedId } = {}) { return storeRecursiveMessage; } const storeRecursiveMessage = useStoreRecursiveMessage(); - function useReadRecursiveMessage(partialRequest = {}, options = { suspense: false }) { + function useReadRecursiveMessage(partialRequest = {}, options = {}) { + var _a; const newRequest = GreeterReadRecursiveMessageRequestToProtobuf(partialRequest); const [request, setRequest] = useState(newRequest); const [isLoading, setIsLoading] = useState(true); @@ -6280,7 +6341,11 @@ export function useGreeter({ id: providedId } = {}) { // we need to use the `reader.response` or `reader.status` during // render where one of them will be defined, i.e., after we've // waited for `reader.promise` via `React.use()`. - const reader = instance.startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey); + // Readers are shared between every component that reads the same + // request, so the first of them decides whether the console warns + // when the read falls behind. + const warnOnFlowControl = (_a = options.warnOnFlowControl) !== null && _a !== void 0 ? _a : true; + const reader = instance.startReadRecursiveMessage(requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey); const [response, setResponse] = useState(reader.response && GreeterReadRecursiveMessageResponseFromProtobufShape(reader.response)); const [aborted, setAborted] = useState(reader.status && GreeterReadRecursiveMessageAborted.fromStatus(reader.status)); // Track which state ID the current `response` and `aborted` belong @@ -6297,7 +6362,7 @@ export function useGreeter({ id: providedId } = {}) { } useEffect(() => { const id = uuidv4(); - instance.useReadRecursiveMessage(id, requestBearerTokenHash, serializedRequest, bearerToken, offlineCacheEnabled, cacheKey, (response) => { + instance.useReadRecursiveMessage(id, requestBearerTokenHash, serializedRequest, bearerToken, warnOnFlowControl, offlineCacheEnabled, cacheKey, (response) => { setAborted(undefined); setResponse(GreeterReadRecursiveMessageResponseFromProtobufShape(response)); }, setIsLoading, (status) => { diff --git a/tests/reboot/greeter_rbt_web.golden.js b/tests/reboot/greeter_rbt_web.golden.js index 554dc3755..9d99fa6ab 100755 --- a/tests/reboot/greeter_rbt_web.golden.js +++ b/tests/reboot/greeter_rbt_web.golden.js @@ -1668,6 +1668,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterGreetRequestToProtobuf(newRequest); @@ -1695,6 +1696,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterTryToConstructContextRequestToProtobuf(newRequest); @@ -1722,6 +1724,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterTryToConstructExternalContextRequestToProtobuf(newRequest); @@ -1749,6 +1752,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterTestLongRunningFetchRequestToProtobuf(newRequest); @@ -1776,6 +1780,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterGetWholeStateRequestToProtobuf(newRequest); @@ -1803,6 +1808,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterFailWithExceptionRequestToProtobuf(newRequest); @@ -1830,6 +1836,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterFailWithAbortedRequestToProtobuf(newRequest); @@ -1857,6 +1864,7 @@ class _Reactively { signal: options === null || options === void 0 ? void 0 : options.signal, bearerToken: context.bearerToken, websockets: context.websockets, + warnOnFlowControl: options === null || options === void 0 ? void 0 : options.warnOnFlowControl, }); const setTypedRequest = (newRequest) => { const typedRequest = GreeterReadRecursiveMessageRequestToProtobuf(newRequest); diff --git a/tests/reboot/ping_api_rbt.golden.py b/tests/reboot/ping_api_rbt.golden.py index 679663ba1..108c3c70b 100755 --- a/tests/reboot/ping_api_rbt.golden.py +++ b/tests/reboot/ping_api_rbt.golden.py @@ -21325,23 +21325,31 @@ async def Describe( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.Ping'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Describe', request=PingDescribeRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -21353,13 +21361,18 @@ async def Describe( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.PingDescribeResponse() - __response__.ParseFromString(__query_response__.response) - yield PingDescribeResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.PingDescribeResponse() + __response__.ParseFromString(__query_response__.response) + yield PingDescribeResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -21386,6 +21399,13 @@ async def Describe( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -21460,23 +21480,31 @@ async def NumPings( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.Ping'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='NumPings', request=PingNumPingsRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -21488,13 +21516,18 @@ async def NumPings( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.PingNumPingsResponse() - __response__.ParseFromString(__query_response__.response) - yield PingNumPingsResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.PingNumPingsResponse() + __response__.ParseFromString(__query_response__.response) + yield PingNumPingsResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -21521,6 +21554,13 @@ async def NumPings( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -24110,23 +24150,31 @@ async def NumPongs( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.Pong'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='NumPongs', request=PongNumPongsRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -24138,13 +24186,18 @@ async def NumPongs( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.PongNumPongsResponse() - __response__.ParseFromString(__query_response__.response) - yield PongNumPongsResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.PongNumPongsResponse() + __response__.ParseFromString(__query_response__.response) + yield PongNumPongsResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -24171,6 +24224,13 @@ async def NumPongs( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -26846,23 +26906,31 @@ async def ListCounters( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.User'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='ListCounters', request=UserListCountersRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -26874,13 +26942,18 @@ async def ListCounters( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.UserListCountersResponse() - __response__.ParseFromString(__query_response__.response) - yield UserListCountersResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.UserListCountersResponse() + __response__.ParseFromString(__query_response__.response) + yield UserListCountersResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -26907,6 +26980,13 @@ async def ListCounters( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -26981,23 +27061,31 @@ async def Whoami( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.User'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Whoami', request=UserWhoamiRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -27009,13 +27097,18 @@ async def Whoami( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.UserWhoamiResponse() - __response__.ParseFromString(__query_response__.response) - yield UserWhoamiResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.UserWhoamiResponse() + __response__.ParseFromString(__query_response__.response) + yield UserWhoamiResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -27042,6 +27135,13 @@ async def Whoami( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -30626,23 +30726,31 @@ async def Value( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.Counter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Value', request=CounterValueRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -30654,13 +30762,18 @@ async def Value( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.CounterValueResponse() - __response__.ParseFromString(__query_response__.response) - yield CounterValueResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.CounterValueResponse() + __response__.ParseFromString(__query_response__.response) + yield CounterValueResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -30687,6 +30800,13 @@ async def Value( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in @@ -30761,23 +30881,31 @@ async def Description( # type: ignore[misc] __query_backoff__ = IMPORT_reboot_aio_backoff.Backoff() while True: __call__ = None + __continuations__ = None try: async with __context__.channel_manager.get_channel_to_state( IMPORT_reboot_aio_types.StateTypeName('reboot.ping.Counter'), __this__._state_ref, ) as __channel__: - __call__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( + __stub__ = IMPORT_rbt_v1alpha1.react_pb2_grpc.ReactStub( __channel__ - ).Query( + ) + + __call__ = __stub__.Query( IMPORT_rbt_v1alpha1.react_pb2.QueryRequest( method='Description', request=CounterDescriptionRequestToProto( ).SerializeToString(), + client_continues_query=True, ), metadata=__metadata__, ) + __continuations__ = IMPORT_reboot_aio_contexts.QueryContinuations( + __stub__, __metadata__ + ) + async for __query_response__ in __call__: # Clear the backoff so we don't wait # as long the next time we get @@ -30789,13 +30917,18 @@ async def Description( # type: ignore[misc] # idempotency key has been recorded; there may # not be a new response. Python callers don't # (currently) care about such an event, so we - # simply ignore it. - if not __query_response__.HasField("response"): - continue - - __response__ = reboot.ping.ping_api_pb2.CounterDescriptionResponse() - __response__.ParseFromString(__query_response__.response) - yield CounterDescriptionResponseFromProto(__response__) + # simply ignore any message without a response. + if __query_response__.HasField("response"): + __response__ = reboot.ping.ping_api_pb2.CounterDescriptionResponse() + __response__.ParseFromString(__query_response__.response) + yield CounterDescriptionResponseFromProto(__response__) + + # Only now that the caller has processed the + # response do we continue past it, so that we + # can't fall behind a server that produces + # responses faster than we consume them. See + # https://github.com/reboot-dev/mono/issues/4754. + await __continuations__.continue_past(__query_response__) except IMPORT_grpc.aio.AioRpcError as error: # We expect to get disconnected from the server @@ -30822,6 +30955,13 @@ async def Description( # type: ignore[misc] ) from None raise + finally: + # Whether we are retrying or giving up, this + # attempt's continuation is about to be + # irrelevant: a fresh `Query` gets a fresh + # window. + if __continuations__ is not None: + await __continuations__.stop() # Keep the original functions on the client, so old code will # continue to work, but use the new 'snake_case' method in diff --git a/tests/reboot/react/test_reactive_reader_flow_control/BUILD.bazel b/tests/reboot/react/test_reactive_reader_flow_control/BUILD.bazel new file mode 100644 index 000000000..621d8064d --- /dev/null +++ b/tests/reboot/react/test_reactive_reader_flow_control/BUILD.bazel @@ -0,0 +1,68 @@ +load("@aspect_rules_esbuild//esbuild:defs.bzl", "esbuild") +load("@aspect_rules_ts//ts:defs.bzl", "ts_project") +load("@rules_python//python:defs.bzl", "py_library") +load("//tests/reboot/react:py_web_test_suite_env.bzl", "py_web_test_suite_env") + +ts_project( + name = "index_ts", + srcs = [ + "index.tsx", + ], + tsconfig = "//tests/reboot/react:tsconfig", + deps = [ + "//:node_modules/@reboot-dev/reboot-web", + "//:node_modules/react", + "//:node_modules/react-dom", + "//rbt/v1alpha1:tasks_js_proto", + "//tests/reboot:greeter_js_proto", + "//tests/reboot:greeter_web_ts_reboot", + ], +) + +esbuild( + name = "bundle", + srcs = [ + ":index_ts", + ], + entry_point = "index.js", + format = "esm", + platform = "browser", +) + +py_library( + name = "test_py", + testonly = True, + srcs = ["test.py"], + data = [ + ":bundle", + ], + visibility = ["//tests:__subpackages__"], + deps = [ + "//reboot/aio:external_py", + "//reboot/aio:react_py", + "//tests/reboot:greeter_servicers_py", + "//tests/reboot/react:web_driver_runner", + ], +) + +py_web_test_suite_env( + name = "test_against_local_envoy_py", + srcs = ["test_against_local_envoy.py"], + browsers = [ + "@io_bazel_rules_webtesting//browsers:chromium-local", + ], + main = "test_against_local_envoy.py", + # This test is not supported on macOS. + py_test_tags = [ + "macos_not_supported", + "requires-linux-x86", + ], + tags = [ + "macos_not_supported", + "requires-linux-x86", + ], + deps = [ + ":test_py", + "//tests/reboot/react:test_against_local_envoy_py", + ], +) diff --git a/tests/reboot/react/test_reactive_reader_flow_control/index.tsx b/tests/reboot/react/test_reactive_reader_flow_control/index.tsx new file mode 100644 index 000000000..c33e5e28c --- /dev/null +++ b/tests/reboot/react/test_reactive_reader_flow_control/index.tsx @@ -0,0 +1,86 @@ +import { WebContext } from "@reboot-dev/reboot-web"; +import { useEffect, useState } from "react"; +import ReactDOM from "react-dom/client"; +import { Greeter } from "../../greeter_rbt_web"; + +const ID = "greeter-flow-control-test"; + +declare global { + interface Window { + // Lets the query continue past the response currently on screen, + // and past every response after it. The test calls this once it + // has made every state change that it wants the backend to have + // had no room to send. + stopHolding: () => void; + } +} + +const App = ({ url }: { url: string }) => { + const [messages, setMessages] = useState([]); + + useEffect(() => { + const abortController = new AbortController(); + + // Whether every response is held back until the test says + // otherwise, and the release of the response held right now. + let holding = true; + let release: (() => void) | undefined = undefined; + + // `window.stopHolding` is assigned here, synchronously, before the + // read below has anything to render, so a test that has seen a + // message rendered knows the hold is in place. + window.stopHolding = () => { + holding = false; + release?.(); + release = undefined; + }; + + const read = async () => { + const context = new WebContext({ url }); + + // We consume the reactive read ourselves rather than through + // `useGreet` so that we decide when each response lets the + // query continue: `reactively()` reports a response as + // processed only once we ask this generator for a next one, so + // a response we have not asked for yet is a response the + // backend has been given no room to follow. + const [responses] = await Greeter.ref(ID).reactively().greet( + context, + { name: "Jonathan" }, + { + signal: abortController.signal, + } + ); + + for await (const response of responses) { + setMessages((messages) => [...messages, response.message]); + + if (holding) { + await new Promise((resolve) => { + release = resolve; + }); + } + } + }; + + read(); + + return () => abortController.abort(); + }, [url]); + + if (messages.length === 0) return <>Loading...; + + return ( +
+

{messages[messages.length - 1]}

+ {/* One message per line, oldest first. */} +
{messages.join("\n")}
+
+ ); +}; + +export const render = (url: string) => { + const root = ReactDOM.createRoot(document.getElementById("root")); + + root.render(); +}; diff --git a/tests/reboot/react/test_reactive_reader_flow_control/test.py b/tests/reboot/react/test_reactive_reader_flow_control/test.py new file mode 100644 index 000000000..2532fd539 --- /dev/null +++ b/tests/reboot/react/test_reactive_reader_flow_control/test.py @@ -0,0 +1,142 @@ +import asyncio +import os +import time +from reboot.aio.external import ExternalContext +from reboot.aio.react import QUERY_RESPONSE_WINDOW +from selenium.webdriver.common.by import By +from selenium.webdriver.remote.webdriver import WebDriver +from tests.reboot.greeter_rbt import Greeter +from tests.reboot.react.web_driver_runner import web_driver + +STATE_ID = 'greeter-flow-control-test' + +# Adjectives to write while the browser holds back the response it is +# showing; many more than the backend has room to send without hearing +# back, so that most of them must be skipped. +ADJECTIVES = [ + f'adjective-{index}' for index in range(3 * QUERY_RESPONSE_WINDOW) +] + + +async def test(context: ExternalContext, uri: str) -> None: + """Tests that a reactive reader whose consumer is slow to ask for a + next response falls no further behind than the room the backend + has to send responses, and then skips to the latest state. + + The app in `index.tsx` consumes the reactive read itself and holds + back every response until this test releases it, so every state + change below is known to have completed while the browser had + processed nothing beyond the state it started from. The backend + may therefore send at most a window's worth of responses however + many states are written, and the response that follows them once + the browser catches up must carry the last state written rather + than the next one the backend passed through. Falling that far + behind must also be reported to the browser's console.""" + await Greeter.idempotently(f"Create '{STATE_ID}'").Create( + context, + STATE_ID, + title='Count', + name='Chocula', + adjective='tasty', + ) + + greeter = Greeter.ref(STATE_ID) + + def message(adjective: str) -> str: + return f'Hi Jonathan, I am Count Chocula the {adjective}' + + def rendered_messages(driver: WebDriver) -> list[str]: + """Returns every message the browser has rendered, in order.""" + try: + rendered = driver.find_element(By.ID, 'rendered' + ).get_attribute('textContent') + except Exception: + # The app renders nothing at all until it has a first + # response to show. + return [] + return [line for line in (rendered or '').split('\n') if line != ''] + + # We poll the browser rather than using `reactively()` because what + # we are waiting for is the browser's rendered DOM, which Reboot + # cannot observe. + def wait_for_message_count( + driver: WebDriver, + count: int, + ) -> list[str]: + while len(rendered_messages(driver)) < count: + time.sleep(0.1) + return rendered_messages(driver) + + def wait_for_latest_message( + driver: WebDriver, + latest: str, + ) -> list[str]: + rendered = rendered_messages(driver) + while len(rendered) == 0 or rendered[-1] != latest: + time.sleep(0.1) + rendered = rendered_messages(driver) + return rendered + + with web_driver( + uri=uri, + bundle_js_path=os.path.join(os.path.dirname(__file__), 'bundle.js'), + ) as (driver, port): + # Selenium calls block, so run each of them in a separate + # thread to keep this event loop free for the Reboot calls + # interleaved between them. + await asyncio.to_thread(driver.get, f'http://127.0.0.1:{port}/') + + # The browser renders the state it started from and then holds + # back rather than continuing past it. + rendered = await asyncio.to_thread(wait_for_message_count, driver, 1) + assert rendered == [message('tasty')], rendered + + # Each of these writes has completed by the time the next + # begins, so by the end of this loop the backend has passed + # through every one of these states while the browser has + # processed nothing beyond the one it started from. + for adjective in ADJECTIVES: + await greeter.SetAdjective(context, adjective=adjective) + + # Let the browser consume, which is the first moment the + # backend gets room to produce anything beyond what it sent + # before the writes above began. + await asyncio.to_thread(driver.execute_script, 'window.stopHolding()') + + rendered = await asyncio.to_thread( + wait_for_latest_message, + driver, + message(ADJECTIVES[-1]), + ) + + # The browser rendered the state it started from, whatever the + # backend had room to send while the browser was not + # consuming, and one more response carrying the skip to the + # latest state. Every state in between was skipped, and none + # of them was ever rendered. + assert len(rendered) <= QUERY_RESPONSE_WINDOW + 1, rendered + assert rendered[0] == message('tasty'), rendered + + # The browser warns its developer that it fell behind and + # updates were skipped for it. + console = await asyncio.to_thread(driver.get_log, 'browser') + + stalls = [ + entry['message'] + for entry in console + if 'A reactive query to' in entry['message'] + ] + + assert len(stalls) > 0, console + assert 'Greet` skipped' in stalls[0], stalls + assert 'updates because this client fell' in stalls[0], stalls + + # Catching up gave the backend its room back, so the query is + # not stalled: a state written now still arrives. + await greeter.SetAdjective(context, adjective='delicious') + + await asyncio.to_thread( + wait_for_latest_message, + driver, + message('delicious'), + ) diff --git a/tests/reboot/react/test_reactive_reader_flow_control/test_against_local_envoy.py b/tests/reboot/react/test_reactive_reader_flow_control/test_against_local_envoy.py new file mode 100644 index 000000000..2862e082b --- /dev/null +++ b/tests/reboot/react/test_reactive_reader_flow_control/test_against_local_envoy.py @@ -0,0 +1,12 @@ +from reboot.aio.applications import Application +from tests.reboot.greeter_servicers import MyGreeterServicer +from tests.reboot.react.test_against_local_envoy import ( + web_test_against_local_envoy, +) +from tests.reboot.react.test_reactive_reader_flow_control.test import test + +if __name__ == '__main__': + web_test_against_local_envoy( + test=test, + application=Application(servicers=[MyGreeterServicer]), + ) diff --git a/tests/reboot/reactivity_test.py b/tests/reboot/reactivity_test.py index 488b1cf11..9cbd20f31 100644 --- a/tests/reboot/reactivity_test.py +++ b/tests/reboot/reactivity_test.py @@ -1,17 +1,112 @@ import asyncio +import contextlib +import grpc import unittest +from rbt.v1alpha1 import react_pb2, react_pb2_grpc from reboot.aio.applications import Application +from reboot.aio.contexts import ReaderContext from reboot.aio.external import ExternalContext +from reboot.aio.react import QUERY_RESPONSE_WINDOW from reboot.aio.tests import Reboot +from tests.reboot import greeter_rbt from tests.reboot.greeter_rbt import Greeter from tests.reboot.greeter_servicers import MyGreeterServicer -from typing import Optional +from typing import Any, AsyncIterator, Iterator, Optional +from unittest.mock import patch + +# `title` that marks a `Greeter` as one whose `Greet` reads another +# `Greeter`, named by its own `name`, rather than its own state. +PROXY_TITLE = 'proxy' + +# The real `QueryRequest` and `ReactStub`, captured here so that the +# shims below reach them through a name that patching the module does +# not; going back through the module would make a shim call itself. +QUERY_REQUEST = react_pb2.QueryRequest +REACT_STUB = react_pb2_grpc.ReactStub + + +class QueryRequestWithoutContinuations: + """Constructs a `QueryRequest` the way a client from before + `ContinueQuery` existed did, i.e. without + `client_continues_query`. + + The generated gRPC stub reads `QueryRequest.SerializeToString` off + the class when it is constructed, and the servicer registration + reads `FromString`, so both stay reachable here. + """ + + SerializeToString = QUERY_REQUEST.SerializeToString + FromString = QUERY_REQUEST.FromString + + def __new__(cls, **kwargs: Any) -> react_pb2.QueryRequest: + kwargs.pop('client_continues_query', None) + return QUERY_REQUEST(**kwargs) + + +@contextlib.contextmanager +def query_requests_without_continuations() -> Iterator[list[str]]: + """Makes every reactive reader send a `QueryRequest` the way a + client from before `ContinueQuery` existed did. Both the generated + clients and `reboot.aio.contexts` look `QueryRequest` and + `ReactStub` up on their modules at call time, so patching here + covers both. + + Yields the IDs of the queries this client was driven to continue, + which must stay empty: a client from before `ContinueQuery` existed + had no such RPC to call, so a backend that kept the responses + coming only because this one called it would strand a real old + client.""" + continued: list[str] = [] + + class ReactStub: + + def __init__(self, channel: grpc.aio.Channel) -> None: + self._stub = REACT_STUB(channel) + + def __getattr__(self, name: str) -> Any: + return getattr(self._stub, name) + + def ContinueQuery( + self, + request: react_pb2.ContinueQueryRequest, + **kwargs, + ) -> Any: + continued.append(request.query_id) + return self._stub.ContinueQuery(request, **kwargs) + + with patch.object( + react_pb2, + 'QueryRequest', + QueryRequestWithoutContinuations, + ), patch.object(react_pb2_grpc, 'ReactStub', ReactStub): + yield continued + + +class ProxyingGreeterServicer(MyGreeterServicer): + """A `Greeter` whose `Greet` returns the greeting of the `Greeter` + named by its own `name` when its `title` is `PROXY_TITLE`. Reading + such a `Greeter` reactively therefore transitively reads the other + `Greeter` reactively.""" + + async def Greet( + self, + context: ReaderContext, + request: greeter_rbt.GreetRequest, + ) -> greeter_rbt.GreetResponse: + if self.state.title != PROXY_TITLE: + return await super().Greet(context, request) + + return await Greeter.ref(self.state.name).Greet( + context, + name=request.name, + ) class ReactivityTestCase(unittest.IsolatedAsyncioTestCase): async def asyncSetUp(self) -> None: self._accumulate_task: Optional[asyncio.Task] = None + self._can_accumulate_next_adjective = asyncio.Event() self._accumulated_adjective = asyncio.Event() self._accumulated_adjectives: list[str] = [] @@ -20,22 +115,44 @@ async def asyncSetUp(self) -> None: async def asyncTearDown(self) -> None: if self._accumulate_task is not None: - await self._stop_accumulating_adjectives() + await self._stop_accumulating() await self.rbt.stop() async def start_accumulating_adjectives( - self, greeter: Greeter.WeakReference, context: ExternalContext - ): + self, + greeter: Greeter.WeakReference, + context: ExternalContext, + *, + through: str = 'GetWholeState', + ) -> None: + """Reads `greeter` reactively through `through`, which is + `GetWholeState` or `Greet`, accumulating the adjective that + each response carries.""" - async def _do(): - async for greeter_state in greeter.reactively( - ).GetWholeState(context): - self._accumulated_adjectives.append(greeter_state.adjective) + async def adjectives() -> AsyncIterator[str]: + if through == 'GetWholeState': + async for greeter_state in greeter.reactively( + ).GetWholeState(context): + yield greeter_state.adjective + else: + assert through == 'Greet' + async for greeting in greeter.reactively().Greet( + context, name='Jonathan' + ): + # A greeting ends in "the ". + yield greeting.message.rsplit(' the ', 1)[-1] + + async def _do() -> None: + async for adjective in adjectives(): + self._accumulated_adjectives.append(adjective) self._accumulated_adjective.set() + # Hold up the reactive reader until the test says we + # may consume a next response. + await self._can_accumulate_next_adjective.wait() self._accumulate_task = asyncio.create_task(_do()) - async def _stop_accumulating_adjectives(self): + async def _stop_accumulating(self) -> None: assert self._accumulate_task is not None self._accumulate_task.cancel() try: @@ -50,10 +167,37 @@ async def get_adjectives(self, expected_number: int) -> list[str]: return self._accumulated_adjectives + async def accumulate_until_adjective(self, adjective: str) -> list[str]: + while self._accumulated_adjectives[-1] != adjective: + await self._accumulated_adjective.wait() + self._accumulated_adjective.clear() + + return self._accumulated_adjectives + + async def make_the_client_fall_behind( + self, greeter: Greeter.WeakReference, context: ExternalContext + ) -> None: + """Makes more changes than the window has room for while the + reactive reader started by `start_accumulating_adjectives()` + is still holding its first response, so that the backend ends + up holding one it cannot send, then lets the reader catch up, + which is when the backend skips the updates it merged.""" + adjectives = [ + f"adjective-{index}" for index in range(2 * QUERY_RESPONSE_WINDOW) + ] + + for adjective in adjectives: + await greeter.SetAdjective(context, adjective=adjective) + + self._can_accumulate_next_adjective.set() + await self.accumulate_until_adjective(adjectives[-1]) + async def test_reactive_get_all_state(self) -> None: """ Regression test for https://github.com/reboot-dev/mono/issues/3135 """ + self._can_accumulate_next_adjective.set() + await self.rbt.up(Application(servicers=[MyGreeterServicer])) context = self.rbt.create_external_context(name=f"test-{self.id()}") greeter, _ = await Greeter.Create( @@ -83,6 +227,240 @@ async def test_reactive_get_all_state(self) -> None: await self.get_adjectives(2), ) + async def test_skip_to_latest(self) -> None: + """ + Tests that a reactive reader that can't keep up with the rate of + state changes falls no further behind than its window, and then + skips straight to the latest state instead of working its way + through every state that it missed. + """ + await self.rbt.up(Application(servicers=[MyGreeterServicer])) + context = self.rbt.create_external_context(name=f"test-{self.id()}") + greeter, _ = await Greeter.Create( + context, + "my-greeter", + title="Mr.", + name="Robot", + adjective="reactive", + ) + + # Get the first response, then leave the reactive reader + # blocked; it hasn't asked for a next response yet. + await self.start_accumulating_adjectives(greeter, context) + self.assertEqual(["reactive"], await self.get_adjectives(1)) + + # Change the state many more times than the window gives the + # backend room to send without hearing back. + adjectives = [ + f"adjective-{index}" for index in range(3 * QUERY_RESPONSE_WINDOW) + ] + + for adjective in adjectives: + await greeter.SetAdjective(context, adjective=adjective) + + # Now let the reactive reader consume responses again. It must + # arrive at the latest state... + self._can_accumulate_next_adjective.set() + accumulated = await self.accumulate_until_adjective(adjectives[-1]) + + # ... having seen at most a window's worth of responses on the + # way there rather than one per state change, since the backend + # stopped producing once it had a window's worth outstanding, + # and the states that changed while it waited were skipped. The + # window covers the first response too, and one more response + # carries the skip to the latest state. + self.assertLessEqual( + len(accumulated), + QUERY_RESPONSE_WINDOW + 1, + accumulated, + ) + + async def test_warns_about_a_client_that_fell_behind(self) -> None: + """ + Tests that a backend which skipped updates for a client too + slow to take them warns that it did. + """ + await self.rbt.up(Application(servicers=[MyGreeterServicer])) + context = self.rbt.create_external_context(name=f"test-{self.id()}") + greeter, _ = await Greeter.Create( + context, + "my-greeter", + title="Mr.", + name="Robot", + adjective="reactive", + ) + + # Get the first response, then leave the reactive reader + # blocked; it hasn't asked for a next response yet. + await self.start_accumulating_adjectives(greeter, context) + self.assertEqual(["reactive"], await self.get_adjectives(1)) + + with self.assertLogs( + 'respect.reboot.aio.react', + level='WARNING', + ) as logs: + await self.make_the_client_fall_behind(greeter, context) + + reported = "A client of a reactive query to `GetWholeState` skipped " + + self.assertTrue( + any( + reported in line and "updates because it fell" in line + for line in logs.output + ), + logs.output, + ) + + async def test_method_that_opted_out_of_warning(self) -> None: + """ + Tests that a backend which skipped updates for a client of a + method whose `warn_on_flow_control` option is `false` stays + quiet about it. + """ + await self.rbt.up(Application(servicers=[MyGreeterServicer])) + context = self.rbt.create_external_context(name=f"test-{self.id()}") + greeter, _ = await Greeter.Create( + context, + "my-greeter", + title="Mr.", + name="Robot", + adjective="reactive", + ) + + # `Greet` is the reader that opted out; see `greeter.proto`. + await self.start_accumulating_adjectives( + greeter, context, through='Greet' + ) + self.assertEqual(["reactive"], await self.get_adjectives(1)) + + with self.assertNoLogs( + 'respect.reboot.aio.react', + level='WARNING', + ): + await self.make_the_client_fall_behind(greeter, context) + + async def test_transitive_skip_to_latest(self) -> None: + """ + Tests that a reactive reader that reads through another reactive + reader also doesn't work its way through every state that it + missed while it couldn't keep up. + """ + await self.rbt.up(Application(servicers=[ProxyingGreeterServicer])) + context = self.rbt.create_external_context(name=f"test-{self.id()}") + + greeter, _ = await Greeter.Create( + context, + "my-greeter", + title="Mr.", + name="Robot", + adjective="reactive", + ) + + proxy, _ = await Greeter.Create( + context, + "my-proxy", + title=PROXY_TITLE, + name="my-greeter", + adjective="unused", + ) + + greetings: list[str] = [] + greeted = asyncio.Event() + can_greet_again = asyncio.Event() + + async def accumulate_greetings() -> None: + async for response in proxy.reactively().Greet( + context, + name="Alice", + ): + greetings.append(response.message) + greeted.set() + await can_greet_again.wait() + + self._accumulate_task = asyncio.create_task(accumulate_greetings()) + + async def get_greetings(expected_number: int) -> list[str]: + while len(greetings) < expected_number: + await greeted.wait() + greeted.clear() + return greetings + + # Get the first greeting, then leave the reader blocked. + self.assertEqual( + ["Hi Alice, I am Mr. Robot the reactive"], + await get_greetings(1), + ) + + adjectives = [ + f"adjective-{index}" for index in range(3 * QUERY_RESPONSE_WINDOW) + ] + + for adjective in adjectives: + await greeter.SetAdjective(context, adjective=adjective) + + # Now let the reader consume responses again. It must arrive at + # the latest state without seeing every state it missed. Only + # the hop to this reader has a window; the `Greeter` read that + # the proxy does behind it keeps just the latest state it was + # sent. So this reader is a single window behind, plus the one + # response that carries the skip to the latest state. + can_greet_again.set() + + latest = f"Hi Alice, I am Mr. Robot the {adjectives[-1]}" + while greetings[-1] != latest: + await greeted.wait() + greeted.clear() + + self.assertLessEqual( + len(greetings), + QUERY_RESPONSE_WINDOW + 1, + greetings, + ) + + async def test_client_that_never_continues(self) -> None: + """ + Tests that a client from before `ContinueQuery` existed, which + never asks for the query to continue, keeps getting new + responses instead of being stalled waiting for a request that + will never come. + """ + self._can_accumulate_next_adjective.set() + + await self.rbt.up(Application(servicers=[MyGreeterServicer])) + context = self.rbt.create_external_context(name=f"test-{self.id()}") + greeter, _ = await Greeter.Create( + context, + "my-greeter", + title="Mr.", + name="Robot", + adjective="reactive", + ) + + with query_requests_without_continuations() as continued: + await self.start_accumulating_adjectives(greeter, context) + self.assertEqual(["reactive"], await self.get_adjectives(1)) + + await greeter.SetAdjective(context, adjective="realistic") + + # Unlike the tests above, this one never sets + # `_can_accumulate_next_adjective` a second time, so + # nothing here ever tells the backend to carry on. A + # backend that waited to be asked would still be + # holding the second response; getting it is what shows + # that this backend is not waiting for one. + self.assertEqual( + ["reactive", "realistic"], + await self.get_adjectives(2), + ) + + # Getting both responses is only evidence of what an old + # client sees if this one really behaved like one. Had the + # backend stamped IDs on those responses regardless of what + # the client asked for, this client would have continued + # past them and sailed on where a real old client, which + # has no `ContinueQuery` to call, would have stalled. + self.assertEqual([], continued) + if __name__ == '__main__': unittest.main()