From 04956c9226d54def4f8837cbd5e872ebfeb16c27 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 9 Jun 2020 15:23:49 +0300 Subject: [PATCH 01/26] init --- rfcs/text/0012_background_sessions.md | 113 ++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 rfcs/text/0012_background_sessions.md diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md new file mode 100644 index 0000000000000..8cf4fab450335 --- /dev/null +++ b/rfcs/text/0012_background_sessions.md @@ -0,0 +1,113 @@ +- Start Date: 2020-06-09 +- RFC PR: +- Kibana Issue: + +# Summary + +Kibana Background Sessions are a way to execute, track and restore a group of `search` requests, for a specific application configuration, like a single dashboard session or for a SIEM timeline tab. + +They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. + +# Basic example + +## Session Management + +### Starting a new session + +It's an application's responsibility to manage its' sessions. +A session should represent a logical grouping of search requests, i.e. a single dashboard configuration. + +To start a session, an application should call + +`const sessionId = data.search.session.start();` + +Where `data` is the start contract of the data plugin. + +If the application uses the services provided by the `data.search` plugin, it only needs to pass down the `sessionId` to the API, and the `search` service will track and restore requests internally. + + - If the request is issued using the `data.search.search`, use: + ``` + data.search.search({ + params, + sessionId, + } + ``` + - If the request is issued using `SearchSource`, use `searchSource.setSessionId(sessionId)`, before calling `fetch`. + +If the application doesn't use `data.search` services, you may still associate your requests with a `BackgroundSession`, by using the 'backgroundSession` service directly. Examples will be provided in the Detailed Design section. + +### Closing a session + +Each session is automatically closed when a new one is started. You may also call `data.search.session.clear()` to close a session without starting a new one. + +Sessions are also closed automatically when navigating between applications. + +If there is no open session, Kibana will behave as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". + +### Restoring a session + +Restoring a session means loading the results previously generated for each request within the session. + +Doing this requires a `sessionId` and *calling each request with the exact same parameters*. If done the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. + +If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. + +# Motivation + +Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). + +While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. + +The motivation of this RFC is to allow users to: + - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) + - Allow a user to restore a completed long running query, without having to wait. + +# Detailed design + +## High level + +The key + +## Background Session Service + +The main service + +This is the bulk of the RFC. Explain the design in enough detail for somebody +familiar with Kibana to understand, and for somebody familiar with the +implementation to implement. This should get into specifics and corner-cases, +and include examples of how the feature is used. Any new terminology should be +defined here. + +# Drawbacks + +- Background Session keys are stored in memory until a session is actually stored. + - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) + - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). + +There are tradeoffs to choosing any path. Attempt to identify them here. + +# Alternatives + +What other designs have been considered? What is the impact of not doing this? + +# Adoption strategy + +If we implement this proposal, how will existing Kibana developers adopt it? Is +this a breaking change? Can we write a codemod? Should we coordinate with +other projects or libraries? + +# How we teach this + +What names and terminology work best for these concepts and why? How is this +idea best presented? As a continuation of existing Kibana patterns? + +Would the acceptance of this proposal mean the Kibana documentation must be +re-organized or altered? Does it change how Kibana is taught to new developers +at any level? + +How should this feature be taught to existing Kibana developers? + +# Unresolved questions + +Optional, but suggested for first drafts. What parts of the design are still +TBD? \ No newline at end of file From 8d7c5da0068dcbe956125e7ee0480181c47e0ab2 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 9 Jun 2020 15:24:19 +0300 Subject: [PATCH 02/26] init --- rfcs/text/0012_background_sessions.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index 8cf4fab450335..fa75b6e8bf457 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -46,12 +46,18 @@ If there is no open session, Kibana will behave as before, suggesting a user to ### Restoring a session -Restoring a session means loading the results previously generated for each request within the session. +Restoring a session means loading the results previously generated for each request within the session. -Doing this requires a `sessionId` and *calling each request with the exact same parameters*. If done the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. +If, for example, the `sessionId` to be + +Doing so requires a `sessionId` and *calling each request with the exact same parameters*. If the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. +### Embeddable integration + +?? + # Motivation Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). From 77570ee432d4e5d59af632851aff1e8cf7357f87 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 11 Jun 2020 18:52:53 +0300 Subject: [PATCH 03/26] more more more --- rfcs/text/0012_background_sessions.md | 78 ++++++++++++++++++--------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index fa75b6e8bf457..30896ecca8d26 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -8,22 +8,30 @@ Kibana Background Sessions are a way to execute, track and restore a group of `s They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. -# Basic example +# Motivation -## Session Management +Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). -### Starting a new session +While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. + +The motivation of this RFC is to allow users to: + - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) + - Allow a user to restore a completed long running query, without having to wait. -It's an application's responsibility to manage its' sessions. -A session should represent a logical grouping of search requests, i.e. a single dashboard configuration. +# Detailed design -To start a session, an application should call +From the perspective of a user, when he runs a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), he will recieve a notification stating that it can be sent to background, and returned to later. If he chooses to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. -`const sessionId = data.search.session.start();` +## Session Management + +A session is a grouping of search requests, who's results are required to produce a specific view of Kibana. +It's an application's responsibility to manage its' sessions, by using the `data.search.session` APIs. + +### Starting a new session -Where `data` is the start contract of the data plugin. +To start a session, an application should call `const sessionId = data.search.session.start();`, where `data` is the start contract of the data plugin. -If the application uses the services provided by the `data.search` plugin, it only needs to pass down the `sessionId` to the API, and the `search` service will track and restore requests internally. +If the application uses the services provided by the `data.search` plugin, it only needs to pass down that `sessionId` to the search API, and the `search` service will track and restore requests internally. - If the request is issued using the `data.search.search`, use: ``` @@ -42,7 +50,7 @@ Each session is automatically closed when a new one is started. You may also cal Sessions are also closed automatically when navigating between applications. -If there is no open session, Kibana will behave as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". +If there is no open session, Kibana will act as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". ### Restoring a session @@ -58,31 +66,49 @@ If the `sessionId` is not found, the request parameters don't match or the store ?? -# Motivation +## Background Session Service -Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). +The main component of this RFC is the background session service. -While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. +It is a server side service, that tracks and stores sessions and all associated requests. +When a user starts executing a session, the service stores information in memory, until the user decides to "Send to Background" or until the expiration time. +If the use chooses to "Send to Background", all existing session info is saved into a Saved Object as well as subsequent requests with the same seesion ID. -The motivation of this RFC is to allow users to: - - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) - - Allow a user to restore a completed long running query, without having to wait. +When a user wants to restore the session, the service can be user to retrieve the IDs. -# Detailed design +The service offers three public APIs: -## High level +``` + // Track a searchId for a given session + // Automatically called by search_interceptor for each request + data_enhanced.search.session.trackId( + request: KibanaRequest, + sessionId: string, + requestParams: SessionKeys, + searchId: string + ) -The key + // Store session Id, while providing a URL to restore it. + data_enhanced.search.session.store( + request: KibanaRequest, + sessionId: string, + restoreUrl: string + ) -## Background Session Service + // Get the searchId from a given session. + // Automatically called by search_interceptor for each request, if a known sessionId is provided. + const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) +``` + +## Tracking Background Session Progress + +While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. + +During setup, the `data_enhanced` plugin should register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, This task will + +## Search Service -The main service -This is the bulk of the RFC. Explain the design in enough detail for somebody -familiar with Kibana to understand, and for somebody familiar with the -implementation to implement. This should get into specifics and corner-cases, -and include examples of how the feature is used. Any new terminology should be -defined here. # Drawbacks From 53d190b4648e8cd62059b7ce130da736a2a7474c Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 17:34:37 +0300 Subject: [PATCH 04/26] rfc --- rfcs/text/0012_background_sessions.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index 30896ecca8d26..fc4e367061df6 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -20,7 +20,7 @@ The motivation of this RFC is to allow users to: # Detailed design -From the perspective of a user, when he runs a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), he will recieve a notification stating that it can be sent to background, and returned to later. If he chooses to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. +From the perspective of a user, when they run a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), they will recieve a notification stating that it can be sent to background, and returned to later. If they choose to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. ## Session Management @@ -104,11 +104,11 @@ The service offers three public APIs: While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. -During setup, the `data_enhanced` plugin should register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, This task will +During setup, the `data_enhanced` plugin will register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, checking their state with ElasticSearch than updating the state to 'COMPLETE', 'ERROR' or 'EXPIRED' in case the data stored in ElasticSearch was expired. ## Search Service - +The way # Drawbacks From d33fe2fdb935f1d603e6b7087b767106f138ba65 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 17:55:48 +0300 Subject: [PATCH 05/26] rfc --- rfcs/text/0012_background_sessions.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index fc4e367061df6..f542ddba29358 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -124,9 +124,8 @@ What other designs have been considered? What is the impact of not doing this? # Adoption strategy -If we implement this proposal, how will existing Kibana developers adopt it? Is -this a breaking change? Can we write a codemod? Should we coordinate with -other projects or libraries? +Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions. +As long as there's an open session, all of the capabilities mentioned above will be enabled. # How we teach this From 0e03fda617274a96f4d30486d54ec10a0ff841b3 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 18:17:25 +0300 Subject: [PATCH 06/26] rfc --- rfcs/text/0012_background_sessions.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index f542ddba29358..6e93792bd56ee 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -64,7 +64,7 @@ If the `sessionId` is not found, the request parameters don't match or the store ### Embeddable integration -?? +TBD ## Background Session Service @@ -100,7 +100,7 @@ The service offers three public APIs: const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) ``` -## Tracking Background Session Progress +## Tracking Background Session Progress and Completion While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. @@ -108,13 +108,15 @@ During setup, the `data_enhanced` plugin will register a task into the Kibana Ta ## Search Service -The way +Any request executed using `async_search_strategy`, with a sessionId specified, is automatically being tracked by the Background Search Service. +If that sessionId exists, it will be automatically restored from ElasticSearch, instead of being executed again. # Drawbacks - Background Session keys are stored in memory until a session is actually stored. - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). +- Users might send a request to run in the background, even if they only need to view the results one time. Results will be stored for a significant amount of time. There are tradeoffs to choosing any path. Attempt to identify them here. @@ -124,7 +126,7 @@ What other designs have been considered? What is the impact of not doing this? # Adoption strategy -Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions. +Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions (). As long as there's an open session, all of the capabilities mentioned above will be enabled. # How we teach this From 6e0e8fb6c4648656ab2e0bf927f72fae302adc78 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 9 Jun 2020 15:23:49 +0300 Subject: [PATCH 07/26] init --- rfcs/text/0012_background_sessions.md | 113 ++++++++++++++++++++++++++ 1 file changed, 113 insertions(+) create mode 100644 rfcs/text/0012_background_sessions.md diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md new file mode 100644 index 0000000000000..8cf4fab450335 --- /dev/null +++ b/rfcs/text/0012_background_sessions.md @@ -0,0 +1,113 @@ +- Start Date: 2020-06-09 +- RFC PR: +- Kibana Issue: + +# Summary + +Kibana Background Sessions are a way to execute, track and restore a group of `search` requests, for a specific application configuration, like a single dashboard session or for a SIEM timeline tab. + +They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. + +# Basic example + +## Session Management + +### Starting a new session + +It's an application's responsibility to manage its' sessions. +A session should represent a logical grouping of search requests, i.e. a single dashboard configuration. + +To start a session, an application should call + +`const sessionId = data.search.session.start();` + +Where `data` is the start contract of the data plugin. + +If the application uses the services provided by the `data.search` plugin, it only needs to pass down the `sessionId` to the API, and the `search` service will track and restore requests internally. + + - If the request is issued using the `data.search.search`, use: + ``` + data.search.search({ + params, + sessionId, + } + ``` + - If the request is issued using `SearchSource`, use `searchSource.setSessionId(sessionId)`, before calling `fetch`. + +If the application doesn't use `data.search` services, you may still associate your requests with a `BackgroundSession`, by using the 'backgroundSession` service directly. Examples will be provided in the Detailed Design section. + +### Closing a session + +Each session is automatically closed when a new one is started. You may also call `data.search.session.clear()` to close a session without starting a new one. + +Sessions are also closed automatically when navigating between applications. + +If there is no open session, Kibana will behave as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". + +### Restoring a session + +Restoring a session means loading the results previously generated for each request within the session. + +Doing this requires a `sessionId` and *calling each request with the exact same parameters*. If done the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. + +If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. + +# Motivation + +Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). + +While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. + +The motivation of this RFC is to allow users to: + - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) + - Allow a user to restore a completed long running query, without having to wait. + +# Detailed design + +## High level + +The key + +## Background Session Service + +The main service + +This is the bulk of the RFC. Explain the design in enough detail for somebody +familiar with Kibana to understand, and for somebody familiar with the +implementation to implement. This should get into specifics and corner-cases, +and include examples of how the feature is used. Any new terminology should be +defined here. + +# Drawbacks + +- Background Session keys are stored in memory until a session is actually stored. + - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) + - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). + +There are tradeoffs to choosing any path. Attempt to identify them here. + +# Alternatives + +What other designs have been considered? What is the impact of not doing this? + +# Adoption strategy + +If we implement this proposal, how will existing Kibana developers adopt it? Is +this a breaking change? Can we write a codemod? Should we coordinate with +other projects or libraries? + +# How we teach this + +What names and terminology work best for these concepts and why? How is this +idea best presented? As a continuation of existing Kibana patterns? + +Would the acceptance of this proposal mean the Kibana documentation must be +re-organized or altered? Does it change how Kibana is taught to new developers +at any level? + +How should this feature be taught to existing Kibana developers? + +# Unresolved questions + +Optional, but suggested for first drafts. What parts of the design are still +TBD? \ No newline at end of file From a91f7f09a4de956a008c1fcdb2a13cfcff9e4145 Mon Sep 17 00:00:00 2001 From: Liza K Date: Tue, 9 Jun 2020 15:24:19 +0300 Subject: [PATCH 08/26] init --- rfcs/text/0012_background_sessions.md | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index 8cf4fab450335..fa75b6e8bf457 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -46,12 +46,18 @@ If there is no open session, Kibana will behave as before, suggesting a user to ### Restoring a session -Restoring a session means loading the results previously generated for each request within the session. +Restoring a session means loading the results previously generated for each request within the session. -Doing this requires a `sessionId` and *calling each request with the exact same parameters*. If done the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. +If, for example, the `sessionId` to be + +Doing so requires a `sessionId` and *calling each request with the exact same parameters*. If the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. +### Embeddable integration + +?? + # Motivation Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). From 34f17e8ebdd405e22e75941ee6c69ef3f8a322f3 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 11 Jun 2020 18:52:53 +0300 Subject: [PATCH 09/26] more more more --- rfcs/text/0012_background_sessions.md | 78 ++++++++++++++++++--------- 1 file changed, 52 insertions(+), 26 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index fa75b6e8bf457..30896ecca8d26 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -8,22 +8,30 @@ Kibana Background Sessions are a way to execute, track and restore a group of `s They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. -# Basic example +# Motivation -## Session Management +Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). -### Starting a new session +While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. + +The motivation of this RFC is to allow users to: + - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) + - Allow a user to restore a completed long running query, without having to wait. -It's an application's responsibility to manage its' sessions. -A session should represent a logical grouping of search requests, i.e. a single dashboard configuration. +# Detailed design -To start a session, an application should call +From the perspective of a user, when he runs a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), he will recieve a notification stating that it can be sent to background, and returned to later. If he chooses to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. -`const sessionId = data.search.session.start();` +## Session Management + +A session is a grouping of search requests, who's results are required to produce a specific view of Kibana. +It's an application's responsibility to manage its' sessions, by using the `data.search.session` APIs. + +### Starting a new session -Where `data` is the start contract of the data plugin. +To start a session, an application should call `const sessionId = data.search.session.start();`, where `data` is the start contract of the data plugin. -If the application uses the services provided by the `data.search` plugin, it only needs to pass down the `sessionId` to the API, and the `search` service will track and restore requests internally. +If the application uses the services provided by the `data.search` plugin, it only needs to pass down that `sessionId` to the search API, and the `search` service will track and restore requests internally. - If the request is issued using the `data.search.search`, use: ``` @@ -42,7 +50,7 @@ Each session is automatically closed when a new one is started. You may also cal Sessions are also closed automatically when navigating between applications. -If there is no open session, Kibana will behave as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". +If there is no open session, Kibana will act as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". ### Restoring a session @@ -58,31 +66,49 @@ If the `sessionId` is not found, the request parameters don't match or the store ?? -# Motivation +## Background Session Service -Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). +The main component of this RFC is the background session service. -While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. +It is a server side service, that tracks and stores sessions and all associated requests. +When a user starts executing a session, the service stores information in memory, until the user decides to "Send to Background" or until the expiration time. +If the use chooses to "Send to Background", all existing session info is saved into a Saved Object as well as subsequent requests with the same seesion ID. -The motivation of this RFC is to allow users to: - - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) - - Allow a user to restore a completed long running query, without having to wait. +When a user wants to restore the session, the service can be user to retrieve the IDs. -# Detailed design +The service offers three public APIs: -## High level +``` + // Track a searchId for a given session + // Automatically called by search_interceptor for each request + data_enhanced.search.session.trackId( + request: KibanaRequest, + sessionId: string, + requestParams: SessionKeys, + searchId: string + ) -The key + // Store session Id, while providing a URL to restore it. + data_enhanced.search.session.store( + request: KibanaRequest, + sessionId: string, + restoreUrl: string + ) -## Background Session Service + // Get the searchId from a given session. + // Automatically called by search_interceptor for each request, if a known sessionId is provided. + const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) +``` + +## Tracking Background Session Progress + +While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. + +During setup, the `data_enhanced` plugin should register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, This task will + +## Search Service -The main service -This is the bulk of the RFC. Explain the design in enough detail for somebody -familiar with Kibana to understand, and for somebody familiar with the -implementation to implement. This should get into specifics and corner-cases, -and include examples of how the feature is used. Any new terminology should be -defined here. # Drawbacks From 8472ee3bd077e290c711913820f848bbe78a02b6 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 17:34:37 +0300 Subject: [PATCH 10/26] rfc --- rfcs/text/0012_background_sessions.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index 30896ecca8d26..fc4e367061df6 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -20,7 +20,7 @@ The motivation of this RFC is to allow users to: # Detailed design -From the perspective of a user, when he runs a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), he will recieve a notification stating that it can be sent to background, and returned to later. If he chooses to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. +From the perspective of a user, when they run a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), they will recieve a notification stating that it can be sent to background, and returned to later. If they choose to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. ## Session Management @@ -104,11 +104,11 @@ The service offers three public APIs: While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. -During setup, the `data_enhanced` plugin should register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, This task will +During setup, the `data_enhanced` plugin will register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, checking their state with ElasticSearch than updating the state to 'COMPLETE', 'ERROR' or 'EXPIRED' in case the data stored in ElasticSearch was expired. ## Search Service - +The way # Drawbacks From 7b749bd259cfee64ad769241998717059278f491 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 17:55:48 +0300 Subject: [PATCH 11/26] rfc --- rfcs/text/0012_background_sessions.md | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index fc4e367061df6..f542ddba29358 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -124,9 +124,8 @@ What other designs have been considered? What is the impact of not doing this? # Adoption strategy -If we implement this proposal, how will existing Kibana developers adopt it? Is -this a breaking change? Can we write a codemod? Should we coordinate with -other projects or libraries? +Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions. +As long as there's an open session, all of the capabilities mentioned above will be enabled. # How we teach this From 344a0bbade912ad2fb50a71ad8d6174eb6db3564 Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 14 Jun 2020 18:17:25 +0300 Subject: [PATCH 12/26] rfc --- rfcs/text/0012_background_sessions.md | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index f542ddba29358..6e93792bd56ee 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -64,7 +64,7 @@ If the `sessionId` is not found, the request parameters don't match or the store ### Embeddable integration -?? +TBD ## Background Session Service @@ -100,7 +100,7 @@ The service offers three public APIs: const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) ``` -## Tracking Background Session Progress +## Tracking Background Session Progress and Completion While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. @@ -108,13 +108,15 @@ During setup, the `data_enhanced` plugin will register a task into the Kibana Ta ## Search Service -The way +Any request executed using `async_search_strategy`, with a sessionId specified, is automatically being tracked by the Background Search Service. +If that sessionId exists, it will be automatically restored from ElasticSearch, instead of being executed again. # Drawbacks - Background Session keys are stored in memory until a session is actually stored. - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). +- Users might send a request to run in the background, even if they only need to view the results one time. Results will be stored for a significant amount of time. There are tradeoffs to choosing any path. Attempt to identify them here. @@ -124,7 +126,7 @@ What other designs have been considered? What is the impact of not doing this? # Adoption strategy -Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions. +Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions (). As long as there's an open session, all of the capabilities mentioned above will be enabled. # How we teach this From 52b78f4fd8fafaf46444279c208a067fd314f6d6 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 21 Jul 2020 14:56:40 -0700 Subject: [PATCH 13/26] Update RFC --- rfcs/text/0012_background_sessions.md | 301 +++++++++++++++++++------- 1 file changed, 223 insertions(+), 78 deletions(-) diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md index 6e93792bd56ee..1691c5a823161 100644 --- a/rfcs/text/0012_background_sessions.md +++ b/rfcs/text/0012_background_sessions.md @@ -1,124 +1,259 @@ -- Start Date: 2020-06-09 -- RFC PR: -- Kibana Issue: +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- RFC PR: (leave this empty) +- Kibana Issue: (leave this empty) -# Summary +- Architecture diagram: https://app.lucidchart.com/documents/edit/cf35b512-616a-4734-bc72-43dde70dbd44/0_0 +- Mockups: https://www.figma.com/proto/FD2M7MUpLScJKOyYjfbmev/ES-%2F-Query-Management-v4?node-id=440%3A1&viewport=984%2C-99%2C0.09413627535104752&scaling=scale-down +- Old issue: https://github.com/elastic/kibana/issues/53335 +- Background search roadmap: https://github.com/elastic/kibana/issues/61738 +- POC: https://github.com/elastic/kibana/pull/64641 -Kibana Background Sessions are a way to execute, track and restore a group of `search` requests, for a specific application configuration, like a single dashboard session or for a SIEM timeline tab. +# Summary -They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. +Background Sessions will enable Kibana applications and solutions to start a group of related search requests (such as +those coming from a single load of a dashboard or SIEM timeline), navigate away or close the browser, then retrieve the +results when they have completed. + +# Basic example + +At its core, background sessions are enabled via several new APIs: +- Start a session, associating multiple search requests with a single entity +- Save the session (and continue search requests in the background) +- Restore the background session + +```ts +const searchService = dataPluginStart.search; + +if (appState.sessionId) { + // If we are restoring a session, set the session ID in the search service + searchService.session.set(sessionId); +} else { + // Otherwise, start a new background session to associate our search requests + appState.sessionId = searchService.session.start(); +} + +// Search using the generated session ID. If this is a restored session and the search requests have already completed, +// this should return quickly. +const response$ = await searchService.search({ + params, + sessionId, + options, +}); + +// When the user decides to send to background and move on, create the saved object associated with this session. +// Make sure to store any app state needed to restore this view and the exact search requests from before. +searchService.session.save({ + appState, + restoreUrl, +}); +``` # Motivation -Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). +Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use +cases where cost is more of a concern than speed (such as year-over-year reports, historical or audit data, batch +queries, etc.). When running slower searches on "cold" storage or frozen indices, users encounter timeouts after 30 +seconds by default. + +In 7.7, with the introduction of the `_async_search` API in Elasticsearch, we provided Kibana users a way to bypass the +timeout, but users still need to remain on-screen for the entire duration of the search requests. + +By default, when a user navigates away before search requests finish, we cancel them. This is a good default behavior, +since there currently isn't any way for the user to later return to the results. -While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. +The primary motivation of this RFC is to enable users to do the following without needing to keep Kibana open, or while +moving onto other work inside Kibana: -The motivation of this RFC is to allow users to: - - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) - - Allow a user to restore a completed long running query, without having to wait. +- Run long search requests (beyond 30 seconds) +- View their status (complete/incomplete) +- Cancel incomplete search requests +- Retrieve completed search request results # Detailed design -From the perspective of a user, when they run a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), they will recieve a notification stating that it can be sent to background, and returned to later. If they choose to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. +Because a single view (such as a dashboard with multiple visualizations) can initiate multiple search requests, we need +a way to associate the search requests together in a single entity. We call this entity a `session`, and when a user +decides that they want to continue running the search requests while moving onto other work, we will create a saved +object corresponding with that specific `session`. + +We will expose a new `session` service inside of the `data` plugin `search` service. The service will expose APIs for +the following: + +- Starting a new session (generating a unique identifier for this specific grouping of search requests) +- Saving a session (creating the saved object using that ID) +- Getting a list of sessions for the current user (including status, any necessary application data, and a URL to +restore the view) +- Cancelling an incomplete session (deleting the saved object and cancelling any incomplete search requests) +- Restoring a session (allowing search requests to resume instead of restart) + +We will also modify the existing `search` API exposed by the `data` plugin `search` service to optionally accept an +additional parameter, the `sessionId`, which will allow search requests to *resume* instead of *restart*. When +"restoring" a session, it is crucial that search requests are sent with *identical* search request parameters as were +sent originally. (For example, relative date ranges should be converted to absolute before passing the request to the +`search` service.) + +Applications query data from Elasticsearch on behalf of the end user in a variety of ways: + +- Using `SearchSource` (our higher-level abstracted search API, used by Maps, Lens, and most visualizations, exposed by +the `data` plugin `search` service) +- Using `search` (our lower-level search API that accepts raw Elasticsearch query DSL, used by Vega and Timelion, +exposed by the `data` plugin `search` service) +- Exposing a route that bypasses our `search` services and queries Elasticsearch directly, then manipulates the data +before returning a response (as in the case of TSVB and most solutions) + +The proposed APIs provide the tools necessary to run long search requests, view their status, cancel incomplete search +requests, and retrieve results, regardless of the mechanism used to query Elasticsearch. + +## Background session service + +The primary service which will facilitate background sessions is the server-side `session` service. + +When a `search` request is handled, and it contains a `sessionId`, the service will query Elasticsearch to see if there +is already a saved object for that session. If there isn't, then we will forward the search request to Elasticsearch and +receive an ID specific to that search request. We store that ID in memory, keyed off of a hash of the request parameters +and the current username. + +We will then periodically query Elasticsearch to see if there is a saved object for that session (meaning the user has +elected to continue the requests in the background). If we find a saved object, then we will update it to contain the +search ID keyed off of the request hash, and remove it from memory. + +Then, in the future when the same `sessionId` is sent with identical request parameters, we will retrieve the saved +object. Instead of sending all of the request parameters to Elasticsearch (and restarting the search), we will look up +the search ID, and send that to Elasticsearch (resuming the search). If that specific search request has completed in +Elasticsearch, the results will be available immediately. + +By default, results are stored in Elasticsearch for 5 days. We may consider adding an advanced setting that will allow +overriding this default. + +The background session service will also use the task manager to periodically monitor the status of incomplete +background sessions. It will query the list of all incomplete sessions, and check the status of each search that is +executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of +`complete`. + +## Server APIs -## Session Management +The following APIs are exposed by the server-side `data` plugin start `search` service: -A session is a grouping of search requests, who's results are required to produce a specific view of Kibana. -It's an application's responsibility to manage its' sessions, by using the `data.search.session` APIs. +```ts +session.getAll() +``` -### Starting a new session +Retrieves all of the background session saved objects for the current user. (We can filter it to the current user +because when the saved object is created, we store a hash of the current user's username inside the object.) -To start a session, an application should call `const sessionId = data.search.session.start();`, where `data` is the start contract of the data plugin. +--- -If the application uses the services provided by the `data.search` plugin, it only needs to pass down that `sessionId` to the search API, and the `search` service will track and restore requests internally. +```ts +session.get(sessionId) +``` - - If the request is issued using the `data.search.search`, use: - ``` - data.search.search({ - params, - sessionId, - } - ``` - - If the request is issued using `SearchSource`, use `searchSource.setSessionId(sessionId)`, before calling `fetch`. +Retrieves the saved object for this `sessionId` (if there is one), including the request/search ID hash, status +(complete/incomplete), application data, and restore URL. -If the application doesn't use `data.search` services, you may still associate your requests with a `BackgroundSession`, by using the 'backgroundSession` service directly. Examples will be provided in the Detailed Design section. +--- -### Closing a session +```ts +session.save(sessionId, restoreUrl, appData) +``` -Each session is automatically closed when a new one is started. You may also call `data.search.session.clear()` to close a session without starting a new one. +Creates the saved object for this background session. Used when a user chooses to "send to background." -Sessions are also closed automatically when navigating between applications. +--- -If there is no open session, Kibana will act as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". +```ts +session.delete(sessionId) +``` -### Restoring a session +Deletes the saved object for this background session, and cancels all incomplete search requests for this session. -Restoring a session means loading the results previously generated for each request within the session. +--- -If, for example, the `sessionId` to be +```ts +session.getSearchId(sessionId, searchRequest) +``` -Doing so requires a `sessionId` and *calling each request with the exact same parameters*. If the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. +Used internally by the search service when a search request is handled to look up the search ID (if there is one) for +this `sessionId` and `searchRequest`. If bypassing the `search` service, this would need to be called manually when a +search request is handled. -If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. +--- -### Embeddable integration +```ts +session.trackSearchId(sessionId, searchRequest, searchId) +``` -TBD +Used internally by the search service when the first response from Elasticsearch is received. After this is called, the +search service will periodically monitor if a saved object is created for this `sessionId`, and will update it to +include this `searchRequest`/`searchId` association. If bypassing the `search` service, this would need to be called +manually when the first response from Elasticsearch is received. -## Background Session Service +## Public APIs -The main component of this RFC is the background session service. +The following APIs are exposed by the public-side `data` plugin start `search` service: -It is a server side service, that tracks and stores sessions and all associated requests. -When a user starts executing a session, the service stores information in memory, until the user decides to "Send to Background" or until the expiration time. -If the use chooses to "Send to Background", all existing session info is saved into a Saved Object as well as subsequent requests with the same seesion ID. +```ts +session.start() +``` -When a user wants to restore the session, the service can be user to retrieve the IDs. +Starts a new session and returns the `sessionId`, a unique ID for this session that will be sent in `search` requests. -The service offers three public APIs: +--- +```ts +session.set(sessionId) ``` - // Track a searchId for a given session - // Automatically called by search_interceptor for each request - data_enhanced.search.session.trackId( - request: KibanaRequest, - sessionId: string, - requestParams: SessionKeys, - searchId: string - ) - - // Store session Id, while providing a URL to restore it. - data_enhanced.search.session.store( - request: KibanaRequest, - sessionId: string, - restoreUrl: string - ) - - // Get the searchId from a given session. - // Automatically called by search_interceptor for each request, if a known sessionId is provided. - const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) + +Sets the `sessionId` that is sent in `search` requests to the given ID. Used when restoring a background session so that +search requests may resume instead of restart. + +--- + +```ts +session.clear() ``` -## Tracking Background Session Progress and Completion +Clears the current `sessionId` so that future `search` requests do not contain a `sessionId`. Automatically called when +users navigate between applications in Kibana. -While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. +--- -During setup, the `data_enhanced` plugin will register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, checking their state with ElasticSearch than updating the state to 'COMPLETE', 'ERROR' or 'EXPIRED' in case the data stored in ElasticSearch was expired. +```ts +session.getAll() +session.get(sessionId) +session.save(sessionId, restoreUrl, appData) +session.delete(sessionId) +``` + +These APIS make a request to the corresponding server-side API with the given parameters. + + +# Limitations + +In the first iteration, cases which require multiple search requests to be made serially will not be supported. The +following are examples of such scenarios: -## Search Service +- When a visualization is configured with a terms agg with an "other" bucket +- When using blended layers or term joins in Maps -Any request executed using `async_search_strategy`, with a sessionId specified, is automatically being tracked by the Background Search Service. -If that sessionId exists, it will be automatically restored from ElasticSearch, instead of being executed again. +Eventually, when expressions can be run on the server, we will facilitate these use cases by adding support for +background expressions in the background session service. # Drawbacks -- Background Session keys are stored in memory until a session is actually stored. - - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) - - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). -- Users might send a request to run in the background, even if they only need to view the results one time. Results will be stored for a significant amount of time. +One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase +load on the Elasticsearch server. Whether or not this may or may not be significant is something that should be +investigated. -There are tradeoffs to choosing any path. Attempt to identify them here. +Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results +will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the +background session saved object has not yet been updated with the search request ID.) In such cases, the search requests +will need to be restarted. There is also the consideration of the memory footprint of the Kibana server; however, since +we are only storing a hash of the request and search request ID, we do not anticipate the footprint to increase +significantly. We will collect telemetry data to measure this impact. + +The results of search requests that have been sent to the background will be stored in Elasticsearch for several days, +even if they will only be retrieved once. This will be mitigated by allowing the user manually delete a background +session object after it has been accessed. # Alternatives @@ -126,8 +261,16 @@ What other designs have been considered? What is the impact of not doing this? # Adoption strategy -Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions (). -As long as there's an open session, all of the capabilities mentioned above will be enabled. +(See "Basic example" above.) + +Any application or solution that uses the `data` plugin `search` services will be able to facilitate background sessions +fairly simply. The public side will need to create/clear sessions when appropriate, and ensure the `sessionId` is sent +with all search requests. It will also need to ensure that any necessary application data, as well as a `restoreUrl` is +sent when creating the saved object. + +The server side will just need to ensure that the `sessionId` is sent to the `search` service. If bypassing the `search` +service, it will need to also call `trackSearchId` when the first response is received, and `getSearchId` when restoring +the view. # How we teach this @@ -143,4 +286,6 @@ How should this feature be taught to existing Kibana developers? # Unresolved questions Optional, but suggested for first drafts. What parts of the design are still -TBD? \ No newline at end of file +TBD? + +TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES \ No newline at end of file From fef559ec5b3efe624d1f9ca20b0cdcb27302130b Mon Sep 17 00:00:00 2001 From: Liza K Date: Sun, 16 Aug 2020 16:34:48 +0300 Subject: [PATCH 14/26] Update RFC --- rfcs/images/background_sessions_client.png | Bin 0 -> 110580 bytes rfcs/images/background_sessions_server.png | Bin 0 -> 115868 bytes rfcs/text/0012_background_sessions.md | 291 ------------- rfcs/text/0013_background_sessions.md | 467 +++++++++++++++++++++ 4 files changed, 467 insertions(+), 291 deletions(-) create mode 100644 rfcs/images/background_sessions_client.png create mode 100644 rfcs/images/background_sessions_server.png delete mode 100644 rfcs/text/0012_background_sessions.md create mode 100644 rfcs/text/0013_background_sessions.md diff --git a/rfcs/images/background_sessions_client.png b/rfcs/images/background_sessions_client.png new file mode 100644 index 0000000000000000000000000000000000000000..46cb90c93aa32bae2b12dc6c8661e73ebcafa967 GIT binary patch literal 110580 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곤p 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%0A^uUy4zz2yfA1b1EJ#dr56xxJ^R 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 literal 0 HcmV?d00001 diff --git a/rfcs/images/background_sessions_server.png b/rfcs/images/background_sessions_server.png new file mode 100644 index 0000000000000000000000000000000000000000..593db3156f8799c8f8a03b15548381586b92dcb6 GIT binary patch literal 115868 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⪻yexqZfdxom0^afa0a@90-`*#Utc>41{L>OVi=>#2Ps3KsM9J>Kb*O6J>`t0^ zbHjW_bPekSF93aJ*?IwVGUPI0x$JUzIei-Rz{cGF7zfSnA_x-Iqwtun^7!yDs=E1} zv~S4ArOr=qOq!b(#^&gnq=A`Pai|9k9%s|j*HPtBj>SI^coi1G?R5>*L*29U1Ag1N|G(&0|Jwo<~6m?#}OzxvhWMJK6BFp!zMk$9Y~w}ltCr_ zE9Zs@^G(dwsdIgG0Xo%AaGMr9*bD#^0ECf{^Ki)b{1~3PElIR(;=TZkCDTbF(e_q@ z2;}n6e~!=D$8mGeP27D;-qAaO4w$xKqh<%*df`p>h(whj^RAL^6 z={|rUWxp6Um+=Tr+I)qppzS|q$8Re1f5LBS-*!kzrpD9PMXfpx{j~Wp*YHGr^xJ@{ zLdHUTuTYpYGPwjiw_>=QG|WsmmCZxJ&lPdPCJlH|ZdkdvZ!!^Q_(y)_A7{`_6=Mm- z3JR{vFTmQ{n^QFk=%viQU2R+XL!6-Y`0Ti|d$E>RK0fjCX(xL;%>7xvSMI0bO&;!H zDTvn6WFuzA(GPR~5gmKQqRfd;=3!>HKB7J-so$uuS6Grbkjj;m?hgPxl;>okL6~~Y zr*}%W^%Xn_<$9X|6N!`y^{T5D-2zL1mRtzuiXC3qm;3Yis>ka$%>Cu8Xm*d3_|0h=_!}DalPjKKk;ArU*M2+FDN0z^ zvmD%&INukvejv4v7_{j)5)pUkbO_}DJSBEt5J*TxXU#LVL(9*W00iz-qH7JH%Sl=h z2^23uCo1@WFs6^AZ2j_cT&1rE`;U*hae7%qD_L(Kk>?CwVD&tv%i@?8Xj0oWk7K5o z3$%`2z^K=^wpMt)CF1QPwPq-xzXw{tn_a|O*-)ZtxAo;j984=w1as-u$5$1=)~`g! z%RkQpT9Cs(MvnFW)=Ejz+`e6>05;$Q!6t|l7Ru|p+1t?4x^#G~Ivv~Xos zbiItL$SlqbpU6#J>qz{#VJ>lhJJAb=v#ts0BxY5px8+1&vOIR+@L={`c?`FvpGD`w zv8**00VPj%Y~=%HP1dMuuJ6`H9B>wDZ*3JrRXuS5BBAO;dnUJ(ePAIZn434lP_FSc zQoZ!Zk(yirzP7Xdx)I7KB=mgr_ffb}s~MS(XH6PJymU8y1a3z`tz`~i+>b-clnZen zW(j&ea-?#EUXF{h$EqbIHd~UFzO94-K}>xkXd2qlP*TuIY(_2e?PKJmeZBDWjhyfK z^(p)ruvC~8&`uOywFi3O&M8h(a>r@9S~n%S5(vhcP6?G{L@oe9&jlJ#huAkfXY=r;z)4>OzCm;Uw1l}8$#TvL~ zbP;LubW3;g_GV|L&aMxLycQi0xK(KD0jvVK5b__~sV=eyJ}Q7`eJCtlnA}O zBw7nfToS}s@mo^;bF)%@i;rr^ZIGWlK2W{Zc)R|cxj&u;z_nn$fuMV61(*3O0ylWh z33Hb9;Be@W((!>0edg7fTJKxEIACZHPRJpk^;$sp@x6|h-?Hi5uB z6atGaJ#h5Pn<+sC$57qu`#nO)W@phx?H&#IByQ~I!7@$RwBoxR!L@FYYVH~&6+~59 zGe`>nxCk>H7I=`kI}S9=!Tbe_ql}^?c65~Py(N-tqm2Z1(Ks$+6vZOcC1vWWnN}W1 z2MfXn9Z$50F_vvHH$O+Bd~R~fFCf7X*j=6u4+0CVRh{6k3<0u|^2XAT`&KN+<%G<* ztbB1c_1Ww3gCXP=N!5rH`!yRT2egI`E6jg$|q99jXSfbp) zHfN+5aMXxHPw!8-v4KYT!>50gcE8&hWkdlYu2^)UoXDUs_yftRCw}Ajgs6fD2>gQv zdH>^M0~MrrQ5P!WF?;!?mEr?C%69`gZAm5ayda;1-QftXsZ6*jf-R?Wi;X=cpU{Re z`vFb?%t#8bgwnxBz%sje_t2kzg{0NQglJPxzurOfGP=2n4vkhF5-Y6TTfXPNDA)r6 zSW(Dn2!=GtJ4!E-kySa4i)-)cnET1&M0@WUOraFN^GX1gHS_{Luug(+;zw8D^GAbf zKF=8s(wJ4q_|-I5xp}}Bl`W|892{7rk7U{lk|Rw^s((?i6Y3L3leT7rXFqO1(c3g} z|LKrFQ;vQF{~rT(!bXr&7?Nn_U|;fMg8Ro_IV-V+_1Vzg{WlMe6DRa4VS!ntVm2W0 ze&@pk!+A}Rw4RY#ygS7)>u2GyJU6e@7B~uL#gFoNp80q{AngN6a{Otw%HEy|&>GTzov{&Ea$4ACaysVmaa(kb$WmTvjRYg%msF1me38BB zyc$=I=HKUqOArMqF4P_w*t@$e{*z)qP6}b*)I_)a2VkTNYy>A#A8PZyg{=g+=dM(i8U_ zUZ#(SX5Ns1XbS$dYU`8gUt%-YRZB`3m5`3a?|XxFKQ@5S(Q#Mq=n>1)EiN;lP|*7S z=TToal7IKq()^PGXTq%)w!Ia4Sbx~%_4+3$0bzB>q#Bk!07u=Pz3(?azV+O6Sds50 ze^Wwos&Rv2Z>B9Ry(Z0$s30G77|}YlJ?E}cRdaU4caMIhH|bP$Orsz>m5?_k>z6&j zvO}wZHEvFsTp9w!z(?tsBP&o$tzuRYUwE9yCS|TQFJDMv=wxZVmyLY>-Q42?XOmwG z(WKPjZHxjl=7pkjEVG7MP*Uabwwh+nVaNN~8AAm{Vw0TyxgkkNk!_68jNkzApdo>y z`tDq6i+bVW+rUE$Wh}L$xhWBibgC?`!x{AEB?u!8CCgn)Zf`SG=fqsMaI`h6>6sR} zVCGb^dB{Uf#dO%w&Vj2XX`|~Ddwu6Rh7tN=41fCG!acU>T;YRirswOUmxkSAZMY^p z{w*>b7BF1lKP2q9#?W%8e}20z-aC*>|4gq)_-%jfG$G|V&k_DHYA9AqQpJ`Mn||E8 zT;WDWE@e)!1<(aFR^-!CI8XS=;8okd@fK^fZ_J;_sCV68)7#FY$adYP1HWWEjl0!j z8aCC*LGP1J<#qfhus}065tzaK&%3kk?!+I827aXZ%L625`p((17@Ya{@uWJ4<<5z6 z)sq`PbFwzS!}MZZCYLW6i$;c$eY}A zfb=%8vD!9%-gv8@XXsErGW;}vk2XKN1UJK2KVIOY@m_?|w0|&@-861B;7K2!+C9lwcaq#IaqF|lRM-1+ zmUsbQ7KbUJZ=XHJ`f1Mh&~<1Vu{;P}!?{Zy>UR`FofpNY$QP8avZX)Vkq1B?5pB<` zwg!!CtdFhE*cafbCA@dqR$LpH(gRX8e<=%P!B6{@><>ANx@CRuHJ~i-~~H%e18lgu^1<;r>-HM zg0DwgfsxE-c|!RuyYt)q&UD1+SzKpOkQ|ATE9NvA^tkw3m%}%_6}qyVa@O;}Y=apD zGB>MVMV;atF#dRCHyE(>XZPD2iArFue$$6LvY}xpvihFj_od;;#T~KZW-v3m1%#OR zZJ3D+CtA+Qi&PVWnPJNWpFw7qiSZ~0(I@%?nrcTyOCz!Z2#Ul0y9??nS$Qt*HoFa* z?&%Hg zI|Ah&+Qd@W{MRCsWw!$yaz=S2+0Diy>KCOIwqik{3@S;8WL{Qy?pC>rA%fcRKLJX5 zbB)(^zE@pvEGRG88DYT|x%|VRqAP0`O*?C$-W209RZE-fLM-Y2%xiDW z^wYR6pyQXm<1&?Xb?$?H1Q@2?tM_P|2@`@3;4;g7Zl3OX6u&dOlw&8?;i zmt2!uL?BfohMS2*_hZl;>SIves9UQh93J$%3jV7O24E34Ac4;AQ*o3zIun>kDWr&ds0B#C3ytNmHEEmon zaM2DNls?h`AlM}aniY-opB{h*F@7j=eGE={4ITmXc4Y0#j$GaRz zAKe0J5`nq1>F=Z6#cSm6(+{R;ZNlVy=iJGCd$#R2UoM-gf$KhNGNJ+I1{TIj^630x z2%9kD_~KFLSfOb2b|upo^Yv?cfN_H_nw$e>|FUQaK3YS3va;_ooW$LKNVNbn{c3%m z?AfV z+P^9WSs$g`(uVk>-=`rp1H03Hljc>OhAvA>_ULR*r&xcVdFf?GY&s*J zI6BSEs0}+ zOGmLOBV(#43IE%x{u3V`_7Yegx%&?RLKSp~fs%svP$bxx<5S==##(>icSm@)KmY&fyM*6ndEP+=eAR&1Ydu-BH# z!-9oCt8tl#nTIyyDWGx1z*Vy9`#p;6=MQ{cHQ@eo8kyJa{i83>gF*MPRzH8cfj#u_ z*RGaABNidR4|8pE31iKc2MvoN|$+so?-f5eTkMrn{=pN!x7 ztb<%GTah=C8$AB`wAW^NT+6{pVlja~PdBUXL^8k~!YjhwC{)%$D6y1%du6n1D!hF( zR=bO|X{z&5ByV}H>{h%9Kq=-CpTuTASULd$XiZp!PK_{{XpwZ$jrKRN^mCIUFZ;L| zA{#(~y+NXEHS{v`)`<4|{F4EDHb&cinL&=)A6#WLQV~uL_^nVJ0QFzXEoDe&_Kz$3 zDgkG^NgI#k5uLT-R-{K$xqWOXFPJ#^&KWzs67{6(ED*ZaV}Le9tT`Wg8L1Q*CUwC9 z+1{g<*0c&s-!;y=dC3CB6A191_9-y06Sgn@Wn%+FqsD$AO{!OcyTa=^)}5UgZQ4`_ zR5@}@Z`D9+p7ghk7K5XmXth}PHFSCnyU0w28B$eN|;$Zvixt1=B0Hr2luGT zw5Lpi12@-qoOQ?htT_x9b3dRl$(w98S>G^Y4ON*jB@S9gBbUqPo*`#zM41DnCE6O8 z0@mizC44!K2j6&TkB-?YzcplRhgI{ZvDoo(z~Y>o@6$$PVa8WPueR4=E9ug5wtBD` z^Y4(W$_TMA)KI%b1PehOF%i3US8B#FKF6|{#3I;_-sdQdDQRA>E6_Gyok366*BZnU z;UqonjU@2kJU^8qaX)l9RK*WkJVgwj_OY(i-NFCm6Y;)*lu;9~L`L+%x()oam1|tO zPaNmV3$_XKi@^6C!9NTJ5ei2*U)j`tG!?xL^+?zxs~8=k-tt6OCgY6YmJ5yJ8(VQj z5n^0c-wno=w1<&S$ONGC&U0zKzIq7J#`OXHly?n!bl*{9f0P_bdn`B*pRG&)9Fz~ z?E&W$c5P(5%-N)UcZsUQ887O4E zPp5@9=(!{f9{fuwJzg&S^aM_pqn3-Pthe@20TG5IGCqTFr2{`=>(zx~QX=U{k*~!U zaYa3n6AE)h8um&0k|xbs=*Nnde-u7SP=;uYY29m^d z)g#WhjWyrqgbR0`bc6-?P!nul$9?ez_8_=l!K|(M)BRtoi1rQS2fh7pn>}$F;>r89 ze)FJZ1NdtkiTY2KrJ-$)y4+v*6@mm_Ijcm<_P!>Gl<<#qSC?~2FGTi1^7-p!Hbac) zLU4bg0(l@X9K7j~_W0h{LD=iJch`6Cp-wQ5uGlnR#in$g#e2Ng! z^;d|Xs_)d=8LF(^N&vYG3I@pN2}QNEgTF?7<44|4n0Tr~cbxEOuy?YJqJ3 zixBxc`t`o8=5?} zEC!^n01=G`VEg`9g8b&d06<%>*TJA3+Pv^tl&W4nhH)y=SMBJuJw+49Zh&IdZ!r%T zsX=)uch$XFe_wvr>y!%XUztTJEoD#z0;0oBwC$}yPy*MLiMvLEQoFX1Z!aC#gk&T_ zv5+SBMP_9S`nrV{Go!sFTvInBQlG4z0WCTz=Cov8fC4JocS?5&l?MN(+hut!Q%0MC z2^U_K4hb=&g#Hfv9@E^7t;dH{l{+yHUe~@=Z`g)M&TWy(nKMECxwVbbMRrAFK9=q_ z$3vPQ`wgmz!edujNsDj@y1UZCrdB$ZWBBBsdg$T6*yc2;xj8HGZ zK9wZhty*2?cP@F|ttwVW$&4u_{CEDaH~5V0(+DT9++r=;Tb}knWAk?JY{p-7WzTpY zni?_I6CY9&no>P8Cbj0|>f^2q1;lUkGFmvkZg<*yCDGKzO8QJ*zTZYB&+v~iY)un` z@Rv9*euauhf1fvKr+I3MY_=KUV*vJnJI8_Y0ynj~t>^;syPgt~*U)1h=H_$4>%wA& zd>2VpVcddzVZ{L$*M26B^iJgV@yXw_7n(=^6RZIwZP+OSNM?2xO_p23ig3o zD}@p`xLf<=88rx{&|mmc{E19*_P!w0z~f2v@R|o;@Ros|hgfIt0cZ?quG6CRf6V!* zlRwWZD{$?WA*!2{i1}f}fabn~pj3!!w{540d@61?X(F=Hq?A%*i0ZtP$h#MEz1?Bb9~@hgLQY8tYi@=cPc}a+{#3nu5Z`1W9Mv%t*E`2vC{8SlrqK{W@J_F z1wYG?NNKU9mnQD_s{Yi3*zlAXJyusSdRWvSus&C9@yyS53!$@ia>lYu4<}YhnsxKZ zSQKI0^TC^ZgDzBW^Hq1iaID*C$1!JY*N!GTHs%nWb$&7oWZM+0kPHqPw{(`k^I~cb zjYhPWpre-{lfqr04Zy$mL4dLbYCgyXO#)?pihCGgZpb#>Vm-is*4%GRplLvh(7HVs zweeI=q=BSE)>21hy$SVv$mK$-Bvf7DU0f0&Uhww}KHH>T?}KehRbS;1`1MSCS;_8g zg8>dNv_$*F>%N#xBPP%{TNU2)v(@)&JOZr4;s2tl|98 zd0!QZL8PU&lqyyZ>yo$7i>|e^vgwUCJ~K}vxJ{sl2}9(B{KI(8@vg4bAwZ=kawJ9Q zZu7PEL?=BHRJQ|l+Wz}s5rC)$jW^uFksa~w4om+bSFh{?>4USjY{GI! z;(c2s$-{cd_43Jr*7a11HyefFQ{nM%D3f)$77AuwFdoWjK?s+jtX(4;5AI$W9p#5H zwv(e0#xEGKP_V%DJ5|RZ%6_6r-tZ1#|3PBT{eBb|I%Vcif}m3F_GnQ{t561VNa#^4 z-RHhp*d1`3`#s}@fyB0HT{5cRuEX9Uean{i1ydgRBqXxV#mA1Fs5LOp`tM&}E z`-`OA58c%yH%Pl~{!~ax*QF#$_D=(9Q=8wBdB1;_BaUa|^qAAKB$Pk49NYRLe$ZsK zx@YJjhA51WqFttp-OYVF4D0qW6XcqU;cW+Zr)kk9F#GIs@nPJTX5d|uHASMBb0v|rY)VDm-*`k|&A^h1pLcG^;p>to6tqZWX z0i7_t;W*HKaaR;K-SJPp+8o>i;bw*N-nlxM`>I$w28Pu6(j_CGq_WxM-H~x=7D=`X z@D>dmp3%2AW0JfZ3k5dY5s7n~@mdV<9xZ&(PK@8HBJ(#al5gab<&KEPdA5^vxZdMY z6BIAm@6#UQw6-|&TAZ-)-m@N*f{5(~e;o0DlUO%N7x=#U9hDQ?)j%yb0tx9n2|P0@XRag{?g1doQEPJl-RFEM(Z6t(u>h;9!9hK`bNx$RLGnd zy~JFs7bRH@-)|4-1eq-0u8j3W4}`@1OylU;Rx_U}E$G-SYJ(G^W`#e}8hn9et12$+ zpLC$33a1w&wD7`_#U9T$XgY)i=B9szxvJ2AkGl1?$!9`**ZnqiVS+b}#-6sqAvZz0=Xd%MQ;6Pubo{EY+?Mlgepe(V&i~pU&A(ylmCzL7UQM zrL#7**$)NPS@;+Kx~gRhZC@uG_C|JNuuE#GpDk(pbaOV*I+Ub-V0f##VbywyNjXdk zb7N&cX=1wzhcD!e8LQTSO4c4piC`c9(9Gj+8a;G9m9flPn4IY=`S&$zrU{9LlgRsU z0e!2kMolffY4)<5n$woI0f;7(LZ#y9SD7E?+u+O)K2ZUQXfi#Dk80?>z7WP z!7;1pV6F9$b(tGRJsT>8lW+SRbl&Tj1ZjPR{n~E7q{Fw1E;HJI%Y+miulJ%Js32>m zj#$2Xlb!bLriiy;q6}MeDR9Kp+4|7A?@ zqjnS!*7NAU7wyUs>%IRd3TcCz*4eU695;!-{hcA~!GcLxCX?MJz#{1FuNz4>r|j7> zhRb9|`^&o89$>(b6zjfi+$s=Gob8K=_RWbE;QS<^P1P<+*RGVb0hF{=fkL(^Xx>#Q zTYZ@;TRnIY(-Vv%J2HT+A$PtV%=c(H8UWn@O1A>%p3l6Y^^brn3(l#6t$S20#fdYM zK={H`BQ}=7Rgi82F15&I9ZhoydtW+Iz44|=dd?o}V!LVB(Owl&rv-5YmqrJjd3*u+ zqLwxfOzzDtYCX9i1DoI-xV9{scEG(rC$FYKAH0>`NF@V}`4?6D(s~#=1%<7jk9t5c z?a4>uOs>Lmw&5KlbY?nJa2)ovse|B_6*)H7xZ{+&+ffcsofQI-eD_wFT;=CbNbc!* zO_%C4#nqP?ysIz}cac6~hpZ{C#O&<_09YR7ogDP+V+!66g>};oSWUe`Db=pq{@OoM zsy(W^{k+da>ix~nS{Yyoi++paPtMYrd=u}C9SC&)$|v#qZ=-!vcc<9w?)yU$;}x^% zuBg92r0v~*tOBl{swSufh+lqKNOS)lE5Pc3=^@U$H!ApsqL z3~Yc}!OIa*_Tiw5SgERjaJkB)uV=rjv}wJNwEh^5{Z_%Q^{mGlLt8V3Wm5dd;ST^Q z`eTXt9LPic@hTQVwILQF?jCAR4)5dW8Fm;ak_iocW&hs2)KCLO_}Rle8W9SzM6WTP z<*NIb#kM@yI5G?>lKTv$A&$Go>3g5q3ntebi@yV!rRP!;mb;k@%EyKnJ^}3M0~`(R zkgV5Sm1)hyJ<9!2aonY9!%9^$p5jp@Fgz(K%p}~LJ{5d>mY6SMTczq>)Ev;K-{+Sc z&YrLFl%-X4r-jCwsr!8x>I(2>C z>+ig-sYWqm{m^L8EyrMbl)EtEM$iWHFMkZM#`{}NpaeLMHqBB%$eQ5ZGV4CyA>}OLb?d=l( zR-A7H8cimTA?-U6r2w9(o$Ql3XsFa;ExSe4a-NT28KbKrPFDMVIyW3ug_4~d!@KhxGFd-S7YdoHZYfrUQ*X#td1qgeKS$fe7rkUu82^P^wHuqF0obul&hLOWZQY^{iV>c_IqNB&4l!?n)nsN2h z?jg9mLxD(&jq5w(soob=2>AFW2Z}5sQMu^&TOzY1cZT57v6*<=(NiSn)-M+t17z?O z0rk;!!=Hkt2W?|-t8pz=qN~?fQ`wogVXf{JUo0Iw;`^l&LP0&u{RKG?EFvmX1mf-p zERUmkZBMc(>W*9J27QDmf6umMnHi8t96P6bmjD+Y|6Yyn@E41dKtVj+;!vN>WVcuf zB8!#k8NbiW3tP={zI}C*Zdvfvryhaw;h!6imDb<9awQ`qJ5N~}gKi=hB<)mwDDBPN zn7agHgRe+*gBS4jS$pSYe3|n4;yl8vgnF1>*%DOwoE;u;?(Zz<0)mDzwI$}k>#T=_ z2c;O-do(h zSI6JS0e-pj)f3yC=Tn*r;Mc}`lC2$3sFYX|`@nF{J*%X-mnLJ~CI2?&-6n-zD5;oQ znKjbd)qzY$yi?Lz?^(SPge|BC?6|ED{@ zapdlTx>%HUO-y>@@h>Sjp(wL`Mi@8J(@#JNU{~3`Yf5af<4l(PJ zo4CJS4AcIEvBC_Vc%pVRCE=6*o+ z3&0Nkv$y-fT}D{zuPn^Rq0x z8$ijW6`!oyvU0;s`?_)u-{(slatx%7$msUH6C4|j;4WFk$=Tz5(k#eLuZwo)*2T)# zxO_IF&HKvUNGLJ|pA!?tyMk+{Qi?Xefr_V@Ptrh7Ixw?4*rhw~dpI^;?n# z-Q2HHY=iIPk?o5~hrX_@vnnvR>maPR>D}Bh4kNQH(|OCx>#iDq4h2d82@M+hoI|Do z5w(AO0`ye+-IW8FN{h>6Jqee;mPcv(QJ{oEWy;BlniaK9ymqQZoX`BZ1cm#RL(wbA zs6sIVagt*dzA|mf^+fIFxvnA}n~=JXiPkiky!qShgFVu8jrlJ~tx~mvyZKcavJdFV z-;cw^?~lF64Xcmn{A()9QW}=RW@E7RL5#K*cNCsI8uIF{O}>a z00B_RWO;#!lMEEn%}wIrtXPE24CN%(TAJ^#NS?-_(O!49ie9gJ7|ePYgw_SnIR8Fw zPcFYgV!Lpl1jgG+9W4oy7`Lmts!*pUX$J#SW_Y_WeH`s|--V}m4f2ut-E+%RZE*b5 zqTklY>RsDZlG%Y?B@pJ_FR@dz)yNW&Qf^o>g%Z6HT!=qO@YkF9- zW4fd(86vX=bUa_HzVD&SKOfA=l!u-9LW1hu$X^!6#R0=_g0lQdDsH2jo0y+C_q#Gw z78^KCBsG%ZbX9-ep0E;og(5Tfe7u^;_mLNjc8kQ_-sma)x_#A$g_;}PjrCP~JRoJ_ z`8%e264y*J&F1M33Y4pG&ZMMLp*j0b7QXDhh+*7)laN2E-XA+&(`a2~e39t3UUo0n z@y`6qkr!!D8tm8MGEuGLVlg(Fq9M3ae=cz|OV(*yb{zd!S3CQgq><9__-H-4>_IjX zevA5!E)CqmVlj^@Se}X0zE->o_sF0Qljc<=E7ET!dhd2O-eqkJCxUvqRjCIn>MJh# z>t2@Ty;GvsNo0r8?$&g~k1ksE4h3D4ox1ODfy-e2<3zEfGkYD6TwX=qDI(Ig+a$Ku zeL-!x_mL%VO2$gYhpZuAquX|1$get5YoqNWb?=VA(iz9n61^oJ5(l0FwVx5wHSBFA ze_2><63#dN^1_)sBW+|BwaG?_!s|LFp~Tq(0}cPM%19ixiu|UM;?bKF(0P)#it6`f zP1Q^OdP{Sos#@t#tz>8WF|PYNtSU^{MGe=68@@!Ru=hVh-8}v;-rh1Ut|n<8o*6Va z!99UMaCZ$((BSUwEY0^%{Z63(^zC0)7}Gd7$Zg#PJlPXwml-Ljk}L_0 z%2x`iw|;uF7C9WsSnCbTqfq>1f8v!We{omT?1(%_Hke=ib!@>u7_aO@ncjN9q@hLN zvdX2tM-fw4_=|*r$UecS z9(@+ID?3}HxNE@#vrZhg2Md!pPM%g0PfOV?wTT`7$8i`mrJulJ^IoM zW`X=+bsdceGRM%js?eblJEM(3bUBh!E!$)kSiatimiMmhK!1*Pa}i#z#NH6=@Jg>^ zs4z^N*r|wTTSbPun+<#U*zGx*>coAcXBP<*Ornp7;3Y$Lk6l)TI{F&K4mEf7MNNrK zMaOO)^99k@C!XTc$Z6;7!ehZcy!#O6O6?8ocnTb{o!BIobk%ExJmf%(xN{OMF(}clG~ANj=~SL zs1gM1Px(O;ac*L@pSkVXu{q>qiHGC}y-(R^!PbT7A@yX`I=E>vRcQ109zP58jQVAJ z87<7HVLznLX#B;uXQb~Eqk@qqX5kslT=?;|FsyaF_Y&MH0mVz-N<{q2ge&W_Er<{H z&vcBVx43OE2;pOanaAbQf3B}Rv9Dk>)fdc_)m%tB6^1#VgdUAuhJxxQQorkN9@7BW zqvqaaRiw1sHkIa=&K803uLMlVv<`l`VL03bNz1 zoNn9c8PC(@>9D*5ib{;u?I)3V%Mw^slaUQA?Gk3Y%3#ULsvCF^UL49 z*+_9H1l$JzY1rv;o?Ga&(9c-{5xcuXfIk_ZD2%pcxubWO_lpJWASHgF%Ajqjk zd_l<|7p3LVgfA;DM|-91Bq<}&pa|arObh<#y36Aovpj>)HI8bY#?$yccgFV@Y4BF$ z%f5D`Oyk2{6YRvY{q=~$63|sMbb9;Mb3+8HJcH6t%q@7Gk@nnu4mS(RjK&g`UzkdP zgOC3#%7Kz#Mgcwrssd!i#mI}gZrY`Pmm0GrqcxF$G|zlK##Z?DhA35zVY~F0ltR(}D=B9NUY9`(oFfyuCw??AWA*+hGVz4V@X$1a^rIq1Z(nmx z>54ypU5egdtf{P`t|6o29!a^Ljvi;L9&bwA)K|<^Ux2$F=l)3e?ZGX%AP2w1<}$4a zi@on-_N4JP&pLOv-jh1`B)4*!nv&w(1m(pln@ks{dljTOqtptYCw}9umY89YoaPIg zkbYGbxA+6oI*X!KHEiSi7A$3$wmd)j?XN0vaT-1`skOn5KTyP z<6Bt7p9j%+fSr?|eVqt<)bQIJt55tc0@enalj2UEc=@8luSBn+FL!)-yf0y!zx3S$ zji%^N?QZlM^G1h{`N)1s25*^6zMn-ZjG!bi;;>jhj%-DBr;9a#4;7ALl-j4CeK#O~ z%xxKX^nBAC+%jgPtbLC^_#j@E@LWEd`-S=LbkFZbK?hOxngQpnUlM7RB$=o+>Ieysa#r`r`;CC8>$!vI3?y0<=ZW`16T zoXDFb2Mps-orxTc5`~CgAMHcpHOA~}V_*MDJMr?HwU+3@?6Nb`>N=1gsl0-+08J$SDxheOLY@~O$ULe;ng@cKe;|HzFOLIa$n_fE+-7@iP!K2Z^6iL}BeHnH7{I^%PjkeSx6hmVcIOI8k9Oqhjr5 z27`S63~TGLfhvPxJ@fPKY%uH({UY+1yt5J^M+GedzV_dTnBNWAPFVl%f5_-U${Uyv zXpujZN6_PzMVC81e2{&Rsre>wFL{;YzF3}0YV;Q=JZv<|e&RtGHCkO6!5YGKWFEy+$k(T7;aqXpJZ%Qmsa&LS%N<+Z8fG8VGbaxx zC;Xya>R%B7XH3Apz9v zulsQ-`s)D;j_2c%eUA54Lfr8sb6Bwpg$xg*jjz;dcGNYAJxd)FCb+VDnZb;hWk`$ym@a6UY{{`BPe zwfUOa$hiNK%u0`4{`$LDSj+7{gfx20ckW8;lv1w5l^#(jic+ry*Xz!ty7-KD9pjvR zn#ugMUe?)X*fBR?HfZQ=w8vMn452#xe8Y{bxY=;?N|}%xeiJiaU<~u(tX;GI*yjUq zT$C>k&#-rnYNKhzl=g2IC(8Ps@iYu zN?YhNNHle#lEyM(5O0~}mT>uE@%ZKA^e_eA_xt=LdiQ=XIt2VOz* zU~azdY9IFd8V=DR|uy!9IP22>?XO1aX*Dg72XcXG#20LgTm*Oor@ZxH>c&KUNXU5A*R?!7mOmr zk?9XD67)>UbKNK?4e*E+%ul6;*EOcE7MT#b88+zSfk>BxLp@MAe$Io;c7cCRs%eW>$Z@*5ReH)Bjp` z3(CJtU{INidF!ey$iF7F23WI~CoiVCPH!LAM}QBk__Qd&RX5xUGT*tzt~2@$EaHmiCjmN!xjWX?1AguJB{v_7r0UPi=a&K-@=}}Wo|Pz z@zfoo7iFoPG$|@L{y#11%-cVhm}yzdKs#AZPh;L8*KVZ+CF z${z|qER6QY;obY2h;@=WbX1s0)uoNvVo@U|v1oKg?L z@8+wI2A(+|vFj+VvTGHuKi75luy$8-r+B^XI?;5;kP*x$5rx2yI3GEdY; z3F^owtCAxJ?}cnV@fy{hR=gmYnk~QqXEz7aP+|`uqv``003-DJdgshT3qnFXGwJ4> z^VeP z1*{JcsxT##UC-%y;;nVHxHrX+C?jcf3F{O)bv7qUyglU&;tJ<{r0>^+VXs4)VL@7U zYy3_Ppe3!iW|>2j^0_ssaq3QoM|wa`9i5o5+6~l2&$m4L=s;BgJyFfe`KV#547PAy zUKb*M;*^PfHR>s}zq?X}_ug)?X3E_VY$yNm1kR2^%(1~r!5`YsO6|ZG3pg%s)7H!` z-Oe(rN8Fg%$-~V}I4vwTbre&km|zE=a;%929UkC#sE>7^MT9#anP5El)JL_TDN(4x zPg_4qSoSS3&W-MOd?UJ;UyXgdy>{kJRZOt;9S>TQ=fp&a!Y4nuGel*ZavVWvO)~m| zZR4=;-uvF(ertu>btMTrUe9 zTB`%9{d8VU z^DM#x&umH|3oGwj#ZKG-5(1!4p1Gc56k&j}feY<(7nd}(7TOVZlliVKno{@EK}7x; zR}bP@qLK=Q`C76U@avHnrIzV&A zT!>nK9(^B9Q+;c&7PVTn6wU|&WWKIs|ze$4x|{VaPaJP;eJa+s^uxGrUIy71p7cgW&a zlZJgMnQc^`F76t%XIqO!RkgFxV&5@+F_DHIlBRbd%P|*ORL<`tzF;IkemXUaJAG)i zUE8oO`89T(9pdJp*!3zN_z7b z91^@CH!1Xz)>zlF0oF_78WSHPh4_*#3#+(f1ug<3@*k5mdBpd)!_37sp7auTquHSe zH*QxLKOG9zx%J*QroGFsOWsYZEr0sQu@z|lFzs@i3^QMD9jyJiBTrHL(?JgzhX%z; z<`V$7$5TMuW8weh-I;}MXak}cED*uw%UtGb4&j#q1OjBqtV@A(zlyQ$ha0t@ds~KE z^yYEPoVe$L5{-ju=E5tfVa(Be4m`H+QuP85*)0u)9X!twluJ20WQyHC)c7YyaO;`W zJ=61V7s{Ticxv==Ud6&tsJ>wShqU|rI{}GnT80L<9J)@SvD{0YlK~>!MNhJT3k1qBGI? z$_gF?G^7AU{r?xj1zKskIy4Wp0KmmUpua9?M5HW#+vEkHzGXT7kMmP79NT+aA4=fX zk>Sr+3`ltqHUo`)|A{Azjz*D7M980j1i*g{OaNF4r2qFn+$me+hMuMd|L0>nF;hoK35BdJ z^R&5lsfmyGG1vn2mN2%zC;#IqCKmtOZ45865$A z34i&kE@7|EMDFg+t4XVO8jbALbkz=iNe-jxc3*+CfgHit&kD$KRMkR~PMkW4#u@lk z3gXtaRI1wr4EJ1BVS5<--O_KY)#vPZ!Fkz|a&$GWQ$OG(X9h|{cB=A9WJbABkKQPr zr{Z(cN$?uiZug7-OrO(ML9`T_Bb|sXBbjx3T@!y%pp+&czV&%W^bPLoV|}JZjt~W3 zgWNQ=dpp}o!(MFL5B+iM*b%AfI^U;B!`3RyB&K^}ClO7zRn9c)!pS^rhU$rk?2kaD)z zJ6 z=OuC&q|z-7n0HG__s`YfaS2oZSd*>fMeGXtlToo8wt`V=$^9~T%FvSUXIwSK{L$2^ z$@~lv=Fhj@Md2GIkH8M>--2|i7tQklNS)Mj( zjl=|{UR-cQID>t!pud|TD_UaIon1u(M#>*bYL}ibT_0&_H z#$LNCRIw2kZ(Rs!<Zhz^5wF!Mm2owI zxQ;6mKS#5LV1?dltT&3+sU3xz;J|61D_0zm1H3___R(Qm+gTBsQf?n3W){3^!d^nq zH?pDZrK{SmnMNiJ_P8gkE{zRt09|I1xt~}zA}cVSNKIrAEa&Ki5{hdaW~N9p=sX1d zsuVh+v)>9_aGm^yft1m_J1565-4NR^=YUWgZgBThl8rRt+@2GVc%EC4j>4JwShY z3PS~)C8q34MHa0H5Q)y$c2NzgN{fDbFpa9aB|MLPqWNGmiLz-G>S|-DRM;xv?)O4~ zFg!MG1l+^{*$aQlD9j{bRQZ9=n?jo|`&ZYMTt+I+^7LzuN#;fzumP!0{0IPupdO$B z9kc17w|^qPP;gsdCr()*pQ@=kc_91q#Ukb5e#%Q6P6yae6l42hUzeI%RVz7yQ_@pl!Te@zKqqbV^Xl4WE>-fYUw?+1G&SWkc+0s6 zUdvBFg07=2#(1I~{jMOd`ABoW)EofhoH^8*M}BDNm9GKx_UrhKAK2kk?1k}eeahu< zHI`qBR2-_)u-cAS@w@3gNX6Mfy&5#-7dvn}7+=dep6%(Jj`Wr;b~(@vuFiv?4)rL> zP$|V=mHG~#G~trvP%s-90I>qwT|*l{z^!bss_lgboLsB4G&9^=xU?yj`wa$@RC^0k zB-$^yyerNe)JhY)`tam4wjrNUoOa?5pEzNYeC62jRpI3MEM~P9b=;)WgTOmz`*mp> z!UphnsZSWbfbpkDn@9>c*C<_^Vnuv&0h4P2!Qj(n4F?5NDOVxS51=W46{VhNY6AlO zSLpWO6=k`i4s1N>k0Gfe;6r(~V)0Q|Ojq+UAt5>bIl2KKV~6(tB2&`-OZNac0+7ONV7 z&gbNH#ApYEammwulQk}*^Tv1Gxo9a4{f~Q)=vhV$wcCV=5^9VtBh3W~=I!~q$c;XZ zkLN3g)11m@4M9J+*N&S(VccdrHJ?zOD#P`!-fV^(ea}_#dpb^bpa-wlf9lE+f=-I~kDamkjH=sz$aAcF_39VEC$ce( z+2v|AUx{C3o0a|9x`n$sRE$DDu|HI;&}D2u<#4KitLk<|SpM|c)Q!|?y8Je&3tMk{ z+9CP`je2#Ot&={TR%emkuxOjgOaVx>Rm%7@xenx65$#M5Tbtvwh`{e))i%<>Fmc+i zFJXvvEXo@(yD*w~Czb<|AE?bsD!J^U9F)W|I`FhL(Wpi6Qa@(^J1pR7X`+@jZ_?Wv zbX+tubDbw%Xs@tG=`HNdy<5nK&h7gIg=BU5+4y6r!hK%78 zn$joxJMB+cr(}nI@chsQ4;J}T!z5R2tks#MLS*H92#esTQux$@X~}X>^a40K3uSdo!yjETbu7mK!IW?%48>sS5Q%a!N%oiO9JCQy^NLg zSLbir4r6vzSuIp+(=%2~+PDxHGfWwJP<*A)(ZduLAy~AVVWRo`^23QZD?%5RVm8+JyD&l zE)^FJ+4{y{4XBP2U2Kd6x=&i$yLPh(?!WZ<=1_Y@gfRN)iJrZ zD|F66w9enpMhRurNs2#pXeH&kO0sD=zjQ@@*3p=Ih^WxbQG>>n`z3*17N-;O04ob! zv%UtK=~JWf-_?LeqtT={LXXjc7lf@szbB2j2%%3-YqL}z&&H-VmQE$z?h@!It|ablxGYFc3QX0V|#z}BIBE)a0IGQa0! zqW{{@!?)xd!NOP+aQ}KhhR30dyyC;d8KRNH*8@Cvc6;)Zl$hDn6?Bjj&_DgJhpr#L zg!z5N{2m6YDj)bv5lL2gOJO^2#IoBqb(!4)k2V8Y{`^~_fJjOt{~^tTC@v8Jif%;U z9Z3GH7w;!;*eu?P%=TKGC=;}3cpXBHc>gst?C^T<2`j*Pf&5#^SM5NzOWFVF;!5by z`xWrg?%yvBr1%Y%sPnJSc3wJdMS=$&L;L;M{xKy16Lzmzmd2=F97(V?*2yrs53Xi2^ggf z`S%BbeoJ=oj}H=KiJz3cc-)nQ2m%f41~*T_{Dx4)dLL2m0pCvc@BguM?7gdvd(`xg z{bJsb#%(2<(!36&{_Jn}B1Lfi=}9RBE}KArc=a_PkkOL-sQV$_V~StwlO00sIVL{h zg}y=5?S}FosxEhYF9xdy_*<07+(9Lsl@{E1Xih};flWB$7;N!8!g$K(VY|-rd zJ|^mOgoE4(lbsU*0CPI^rm#%Fi~PT3*^}m!JSt=5o_ZCW`jW0P5aDM+cX%V6_^*Oz+U-> zg*U5nE3G;gNG&GZ)@s5NeTuf*?5E_#$)-deM68}invhT20doWUzs3B&dUUy<7H+R? z>5up6A|3~xU|`}p*@8hZ(chssupUg?Hlx#Se{WDE^E&^!lm8zE|3}sKaxMkmh0nuu z!xDlQeru7;ctKK-G;+o1treB1wV*6cCe_8U-JG>A$G)k1i_Wk7SwdjmAwM; zxE{n_DJB(c^TTOw%24Piy}NKYjx#aY;3pTrz5MSdj>yE zx_Ai~lU^gafLO+Yr{`J$!r1&Ke-X zu0bD}x=mBnA5i_2{Hc$+kWS}qUns)TK08A{rE>xkt!;WXd$2~!y0KCe# zzFb_`n)CWzAzkQ!iT)jbow+4N&%wVTS~1vrHa_-#JHVfyu38QV1!-R5FY`!x$U)CL z5w27Ne-9(=wdJ#LEK|>gwG3gofA`1o)}&hV;h#PclpF{-ZjlS%xn=aEgiST4v*0d2 zl#DAPXo*7Gv3uG&F<|ANZ|Eo)J=ep4c3~Ogumt<|GQTQ#-psqDQoo`Lj zg?=a!p4a8lS3w6quP9Cgtga1m&p8=$hr-%tsw}1)>kH@Ge7y+$ z9Dk)}RXf%dI?tJ}EGRYDR|0r8Nn}&}bYv$kvX&ovMrP0n4~t%uwVqaP(AXfgQR`;p zkS=5u*p;TmMP$7Nb7!ZdSNF4b;C1vf8`{Wb>4qqD*xtNpKvRDnS7ni{5nrCOPb8L} zl8LNd?aM$U<`%0|2C!0xkk8W_#9L(3%J~<4TB^64p}6s3aXzQXvm8)+`GhbaYNKE4 z6cx+m8T_B_o_h@L`W`cPzJvbIj6FJY=s(c$?k z`?i)nD`CZl5rYxV3`t#n(Mrd<^t_Y3)W(Wi^b0L%xI)gyS?j_@Nyc2;y9mhMpxJfa zjJUb#hmiw4=JJZUn6UoOMKw$V&ulnkW7IK!d`&yyudC$SO6d0ir|Wq=-BzjQq*INz zyE#N)G|N(7G_>bqFfC5KtWdA1xhABeNbY6zsC^SPP-0zh9Va$Y2Qe>7vTc8I)Ei)( zjIQe#TvYd5g79ellt>V7S@exQN@wZJt_Qh(M^V;`#E)}LN(f2Jx$)Y}bUsB3q@9$A z%<8&eZ(5Q>Xo-e)9hYG-HCPv=MGqRjQ}$I0FF^f^*awo!fm~ei8I~mpe&(0Hn*f1n zE9u`46{VqP-=Y=VNN61(q$eMrzVI1uow~m0h>4PcZ*ykyqpTLvxn*m=7dy2*r2P86 zM?w770@uiM%B*=ivfhev99A@;AUf}F;f_kRR7C$nNs%YKz;AaiAJe|@`kmd z(+`|?hQe0fxnsWHJ~g!mB;B_eP+z}%2rcYY7fZZ7Bt6O3zdpeqesj}%-!y@w)g=s@ z-_Ts+q_L=Kgx!}a)USx>Ov z6&bKh7*P=}e3<7K7KOH<{OkO`cX?Og+J*`Q2En?!HXSVEX0X$)V)JXwUDkZ>sU6 zg$c%N;K1v68bh7PY!FX*{Z+h2IzbJOKZ=u75XEU5hjf((<6!8Mnb$-kQ|PC#K=alU z%WAf{X1+Ho>faEq2B&^kbpDsuMn`ojX}DdlcW%Bw)UxPYcH1Z_{>)#)zK+mCq*XmD z3C(60dnvA2Iux8|+2z%(0H#5F{_gg9dcak5tL0F}6atQerDhKG@>7&q#@GQ$w|weA zoYJWCHGDt;BRVM=^uFjnn+%a#p1Nr23O5x_ry>O6?=(q3vr7nGN@_FflL_PYgbh0= zXwEb4Pe$A{KGv>?9TAo8086&vT6kA!4CMfc%EZT|U7=NcFG>HpuuR-}F$n>#`F8~* zkQ4*bDSx%k!{gq)b=@jAeje)67qBO(sn!Bx)|MI*B@>gBgS{Cjf z1LRE|K`&^P`C~rP#*E%F-oi^`!PA{!SA*SjP6-usdJCEgnbJ~gvPYJyZ|QW=+^hKa zTKh-w;hZ5+BUyTJh_{rQXzf8o&);SRb5B#NB3ly%BQAFe5;Nr~EPO z(2tHbT9kItkZ%;_5V!aY<_{{OBw-(q3X+xyTldd!5l1djU%4k<=9D==0At9~EDFT0 zjDAo)Mu*HJR;^aww7Hj;E74JC&YU28TR?dK6mKJQS@*@ZxS6+!&el7j&eQ$ZP*4V@ zFs{&?|B$1=Wf3SN#M;SLAKf$8i4Z~Xq;uqO>+VnsD*o9=6q@pYFDwU@#wQLza@MD% z&5d+Fv9Py{mzyzoc5{H^9r{3(Wo6fVEC(S~r$drYG)C@h1*t9}=JtGwLVGWb4K``R zd7|r;?J|e6{BXyNyL_)o6z|DN4O`j625YRsy}!rdtp|;VA!1gW@F>=sG#Je&cA)J% zYmnX^B5VdK-+YfUw`MMU{O1}B5v~~Jfi>mL&Zq8uuB9S41|bc7HD8N3J;6wz3XxBf zFHgpNNK3YUhtn+TGm*d=%OMFt6n6PU?)N<_-{adygkv&8T zfjNfl;vp{~WjMP^M<4ChH_#@(p+$ku{<|i!&=dmrdh%aJG(jG>sBf;5umh%JOrBjS zVVz<{l}UWqoQnl0D=2(vy=(8&mpl$M!NRCx%ae_98s8hUKjNLb6K?O|D#bBEXVoBnvqRjlX^C34#> zQ$IkSXJhx}jmQ9kTl-lx=n{S1WodI?8B9+6N;^P^4mR*L!Spyz`B_paoyNKYn8bTI zwhyvW{h_he+1^q2t;4B0VpX=mGo4fS_9%yh5aVVa$h_s^55_C|261y;WS=grt6;U( z$4Vo6ytB_9pFx{G`Rsc9E2y;2NcD9zm|-ZZMj;WhFaNPi#csgsm1D?(Y^k{$L7+ zZ)aI8Y>-t0##19L&0Y<~TyLr%i|`^R8wb_Ro)=*^VIkrhYZ?vE2DZ)r*y#6J{o`k#n-bcT$ z!Cimy!?+||Dy~tXa2&#qn}cX;jopt$syM_E%J#{wp>4dT{fVk62fNbt+ z(My#LKfYxaifYt~ZpP*gkDbDT`&uNqx=4nFFSvqODyT0e3F)qBQyRnwq}qNjZzA`e z20kOYGQ@wnAw~5Y;aWW|i=)Z{>8KV6nJ^^)J~zKF#%eH~4&q_n>bPW4*7SJ9f$W`X zy&pj+wJUL7#59whn68D4+%^wQ$?*E^#FO0?pQJ^)d)N~VCd1*j+bz*aO*=7HTyG&v zpP#*{YhaQ$?4YM*WkZ46(9seWH{ixM3h;lc+t?{_3n{iwxPa$R%?@89DW|g{c^z|I-r$)!Nb? zO}Ve&b%8czL#Vi`JL#*49(C!~#mv;ZA887lv#U=TI-j)J7hB74a+IlS6FBc)D0QcN zjQ!bEy>;^S5V>hGN1`Z}hM_T`TPIt#TY^Em>2&)vSB(OGB;R2$s3^!?)lyQ#qthy3 zocXnFhMthyyggyRz#sIa3Vb^%>V@MIwmHUx z+$Efw(lz-X1kfDWRUmUIu5H6gducOQF(cQOHGFvrBZi~*Gn~8zPM{R=Op*aVugHVg zBZ!2$&0tGb^K>6Mp6vNKkG)f6b30Kup6@2#@14cqMhFFRH~&uu)1B9Fi)Bn0 ze~I?J{v#2TBk-Spz*>HZ^bdOry--(mMK{$|^4Q}7I4y8+=~o+dTSO+wK>#ScFh%p3 z&oh`3#y=G5Ekk?7Rr9>$(%}wJIJid4F1z;C^T6GIz4Jdq()elOZSRgXqSY@vnPs;- zK!oMKf(`+RZlLZnHh8Fmv%ZErPWH2<`SF4zD#SNDp%Ii|9tc8q!u#za<=T)ScWeKY zUOLa)?hR!sJLE(_|JFmq+h^dx8vlXyXrzXsT*i4b zQRe1mkY}Snz}WR7#uy~^TNMY=E2vX;%1idDQ?dZ0+!4z=WX`upU<>>J#1f=`>z#Qc z5dJED&5zvWMtPEHV5=(6ti|nMvb`F>JvELkT5X zE(x%mo}$!imk1b`oOUb+Rj@Z`qZagR zF^a;OF>9;4cf_AH2Gt(UxANOGb)tRFm?eJmb4iN(OLbU8?p`s-wbYMX{)4%D zrmknW8uGc5qHuOk{fpo|9^qR(ji?KZ;erRdZx<1YoYrBZtL#HNG=fe#m@_Au-RWC1X9K1W4#rReirS5w?I{7SN$LS>_M?81qHRHsSlqzCAA6Hoit7 zi1`AhVu28FuoLMJC0~mju%+`w67TV8>?j7Q@1D>YFy#_AVO>14ZS2}8^Q~TW!b6taO*_wJqX5|Vw3wi@PxJ_$( zO$|%zQQiW(mkv5jRo}wMW=-PG{FR+vnW*)aehpuGuiLe5Txwr%rP@#L6aK@hgo+|Q zxZ84xyS_-zI?)akKg1`p=%?6M%OZ5*+$28@x9i617mcn(okV<>I^E=eJ9)-?d${OvH8>dtGVnkis7AQV7bUH^QD-GGw=&9J9|5 z|L+f`H&6Z~6VK_$NxlE{Y3lcZ^Qcy&*rX+D7 zdNC|9mmAD)Cklk9xTLN4MM-}6;m6E&t=Hb2($>#6(oprsWtVQnYYNyZG^BzLnWj5Z9rI==}NR9#t!d2T`O8 zajSc=*4z~`3)~3%&wnNFPp@TtM9@#lV`=$#xv{?=SWrWbXGlbxw#l*6}N%L@3gry>!Q&~KNT|jqi_z$@FAWM`-SB$2 zwBu_yo=eBq&1$w=>O=&n)sd-uxZr$&>? zbM?iT{DfhzyoPM&Xt91Kcz#GTmn>2EVL{_*`8D{!wQ!<-U@ADnQD3fRMuQwd5oop(Udg52!Xk0JO;I4d_9VMCVw|szo5IBbM zYD2rNuNkk4zxTd(T~***aTybb%59(6M@{*ueo{={&zn4Bctn3C9rmL#Ae;K)yQ;5D z;ATL5Q=cz&AH(gdiluK>y~s}ADX`8UqRY8UaA1Fze>ubVFqY1`$o;3H9}hUILXHhD zZ)*t_Y6+IT;>h2|Cp|T4@{y`KK5G}CSR3rzotfOeOl==ABG!?~gmYlxb&1P^ zgSfT|i}+{9Wbo6BwwL}C-Wq^!4+M$u{WDNB30Xw#&w)liHGF1?j|igM&%u{UNDf4;vCdhg4El}m>D zW!66706=AU4M{b#P`(cc18##UK>sn%o@V*11CfmVnrMmB^hEocv7+Y06TSI-PYEah zW&}wkn9q3i1tSgZOmVSGgTcPeqT@pP({?A^MJ;^?&cN97Z8#I}d;Ceu*QxqBE=jh0 zZkEgD4zuF+6sWl>tE#9~EFJIMoVe}2mejWXyw7pL7!`K9HV2dE*94Sw3sfv2K^Q~N zJIyzS5e&b>Y2zXvebc%q*OxFW>ZnQ3q;rn*F{TsyCzeY5r~LGOp&KqWI4)1xN|kewv(M!rOWS)~@A zMC)rh59yW8)~pW_g&I6t6GcCgfzny;AR3=w>nQJATI>qOUw4yi27>baKF*qw>r5MZ zzEm8r5UCnL^b-SC%~68&eyg*d9-Qwdjqf8!v0Siq19T_$;-%a4u_;i*QOp@ckUl{u z$DZ@;$WMmlcI?fT9!_{dmV3~Djw@0~&#`Q9v*j+eS_t4$*WYe?gN`1?WtTpHhCZ4= zV@0d<;ELhEA3JMIO}1@lnmX-NUp95tFhjKGQ0=2I5qM4T`m>%ya?~k;Osga}T)6O! zDyCKrtHUf>si(&aX7)74^n>t>Z^UlW-*?Ws?*~OIp_I!NJsCqWf$jzqE+1TDKu?s0#N|_t1DqiQB zR=nsv?56%uHkip!`b(keLmcD7ajBW5UA}4a(i%S?(c&@4Ck<{mulM(t1>ElbI;XO1 zB#JEX2^d3MTL@XxB=gw>%RMZ3_kJ|K7e~(#@R5(MWk68VZKYNI_NH?aT9;VV0gtNP z9VXYC?UtI}^={SEhd7-Y+t7z#X`saJOlR)6w5Y~zA`VpNz*^%mJ}7W3(&6d|vA4cm zjyhqFupacL*45n!!&7C>g3;@)G~M9cLQ>%se#vK*L<=HgENDh1RF-Y;F{qb3xn-TK z9kgRHQYGJM}Q5ZMjZ6+q@t9SCdl4M-ZD{_P}0Tvk=?FGZUwQk1h z6`#QfOns=a)~s_{yOc)thG}i2v~)aLDvL%(zT($Vd=|6#z`V|jm?ZsPHK@CGYtIgU z)1t~n4BFGO<&`s+9mv{SAAV9wktL7+c5%Y4N$oi!=49&J zj3#Y}S~EE~Db>86*yz#g-k;!W++j4}`-a<(Uik+{e+TVyvvp@9Si-JDYO`_l6X2*;$92KfTbmbvvfpPn3+n=!?5x`3dV&Qm&~f z`^5&~OzUq?d7kRMVO;IVJ!E@rdk~!GM#TmPuuNz|v5-MDFko@xhU(6;sOztJ4`o^J zlutIN(oea@quJc(5ti?pzsmDwgz0r#P8}7?Jxkv~2nwAj2jXeG#6;mIqs_HPu6jN* zSA3UMP1F(ItA%=-rnMCFLSP5!*AysDtS-(kyY->y4dncS!^&QYRG1}u_~!A^d;W2L zQ(Qr3a2+9*IM-v#clD-MS+q?f$24Nkx~$(eIvEGp?>g}|z=0L3RxX?vbeFioN}!H< z%-ugKHS3vo-HWJqpn(7(d@0Z@1B0)xVa`)6e5xSD6)c!RLa=^dI)LK6TOER3kyn-W z{M-1UIF7#Z6kT`BthsPccuZeh6YhA0&WxLK?`;nA6OoaV%vIxtfp>Wh({Utm%(7mJ za}C^i56>&d&+p}g=;P2Yi*)HGj`8PXD=LR%s>*ki+(fL~y1((>yFV?ThumGB83SFzH>JLz>?;91CJiho@sS!TbO})&fn8CR0@2~Qh23QZITZ`U zW0O9)80omktn~l^FbHRPQU_|6UN=^d(KGjXLf?0w=wejJK`tdji;q9$&YjQiK3}vs ztG0IT%ob%nP!*Dj`Fst_2nzy6G=j|QTvCmA(1zoSSc$NfVK3`!OdX)42dhGg!vuid z`u~rtw+@JM3Hye3=@0=)Nfo6_x=|1iDd}$M?uHcvq(!7eKtZ}YmRJNtS~`|xR}fHY zL1KX=z8lXu&-=XZ_b)d)bIr_E^SfdcfKCnS5Yw&j`(ikH(;>NEB2`vsa6V}Hd*6V; zxWKgS5m}0m$3#GF60xTXf|4akGg003 zz9GYZ5{~PxW#O1R?|x)6)Aysmnt2YiVbb45Y4z!V(*W^h0&7L{2m;Omwal73MO*(? zhZs*V7}76gJ$u$)IP(41%lMG?UAiNx#iT7GwbQG2&xRYvhIDPoB1^#kZ~}0%M|_?x z^L;S&E8=@#T9r`4ML~EZ@B;QHg0k$FE0pGo3_D~XfN0gf$uR8`{&+o{XY$a;rtht_ z1wXO%_tyCG!nhfZZh-UX{@Gz5iN|khl9QWy9D7v|NT}4ybewQT%mdR~hz#DXDFB6l91w~Q(&tOMs;`MjH%a+qxZ?=oi zAE}TD(gQE3UY`dDRO>F{7dks6bS7U1;*escC8PT4eJgu%{ogZ-G(?)X@p(MD@a)ug zM(lShxM)O-EmiqIbDPS#_-Vo}AFi+e;qUc!TfWfycwq@*$y1f=cCGYXJ%!+)KC3l7BP-MRX8VivX9ptL1x) z&ith+UCh5vZp5c?=)tkOCg3i}4RWnLiPs0=>XTci>4cS_>z(h|oNdp(l6woD3&9Ds zKV3c~Zh8$u=ROYm^Xg|OUTc3Zl?(-il_x&%ZZ~`2XqBJh72++pMWInU#}RRQzHYA! z&u556Wl_8@E%;y~EhU^uYB>~{5mG+Sp%eGk-(~cbDW7BRp7a8(<^Hd^k)a2RlkdGa zL6|fTT8@jG1&r&iv^Q^wmOPRF9KY{TygKdUJjJmX=UsXphaDkn_)&I}mL^neRtw6x zf3DRQDiHyhVCh<_1a0`bVltC6Zm6Jcjr{hNl#I9!Vgdgr`yDH@?PXW)-yo_zByjKX zavN9pe!BUSwZZue`^E87Wlv=vvLwdV#zv?%hw_j+XDGsLZIO0SBZ)o!2L%h9sQPH| zexd%*?wy^RZEDq?gIqa|w|1Sh%IFP;c8l`fJr?`A_VGLplkL;6s#`bzAYOQ4-`60T z@Xe2)M~yOarq5dyQS$CK5+@4l`%}j3;ZCJ-KCS%n3JV0rYQOO zvJa6Q?vK_pyBu+vo2DK=S1eNTR~x31d-OwXmMR1O3Z#3irx<0e?>}}v_q@kIdxn)5 zq5_zae@qD=U*Z_#D7_#L^Tmz)x|DVPIsL&5&JT}FhJDvvt{z6XG+5fXC~KT*<9ly! zava9~=QKxO?wg1KkWXrs`nzM#OHe(t+xAe^hg()ZMhxNiJ_>Vs zH?NB*7&@Wq0I=_`O6_TCnZ0odrNL$2cQN<(xpY~@P4w#Lz?W#qPzia>IX5Kt_Om$y ziRXjP(TweRIrck0*aD3pKHW}lUr&^eX*G5h=z9B66L|`~fF7Kg#IQ(f${xpRNt|{u zRVrwa0^unM9PoN;be8bcDQ@BvcdxfJwbk0B=bYl{YeLf|GB8039v;2fwM-IMcQo1W zBa`TBJs;z05~b5YXH{}pD6JkcCv1LgAi{6ma#16-_^lz#T4WWVr%R`BT5f|*4F2$e zfn(9LGHT|;{%2m{G^3>e+?(X$w2$q8^;w*KTBokp4IDE9(~>ZXDn43`!(qN2vX|RDMo6S_-4bHU<{dC^KWsWS${hZPO--q^G)=+HG+xUOfKS1Xs5;*&ibL=sh{Z%{hzK5=3D=im%^)p^2kN4=w^RHn`90;NtG$ zXBC-ZL}4-K_+ZWBfns_c0W670Z#GV)03|9o6ynIOqKjjOktQY*40J5U%L)nRa@GAF z4wMexxHihDcvBaHD+C0Lj8I5_xhC6NlZn30iN819p*cJqt7y)j&K49O<=P zCg$&MvOh*1G4AD^aLpwrJmHgFAblm?^ud|irNva55|{Uk^&;ovjES!TB#gr~6**Ss zyt?^R#iO^3-fD-jr>txu&TVrv5E9>j7kH(|1fbl>QBPvd3D(4bNA~iafHb&oOhD{a z{`EEkks$qFBiP?EyL|}_#$Be8-=PsWcI#;!oP7nN(^MlZ|8uvWR z(wF6h<$AMK(uCl+YSb4OE!QPk)2fQ_!E&X;rb_4e@VC0O1~z!wD=UlBR&7*%L7NhwhB9YvQhoT#g~FQ;!l;_$o&)`(Tqr=?bt`p z^Gb8gt;w|py#zf0ntW-W&8MdL1(sWHvbQOFHghg{)-e6qxAMK#kW7PtC*%@f<>7mw0+UtsWBy;UMXf9cCC1rw^QCk^R4=}XKk5t=TE+AoWfW zYIswH!d!>hSeV)_9~!usTqzY%A6hGOvc(UPSFoH_`~+=FU)BPB7}o}ik#C5Y0UdL2 zon?roz5>=GyY=U6d*M~}B82s=nGt$sRgMM(;#qkOYB853i3IlZjqel&7mt3V4I5^!uuzZW(!Jrh|Rh}b-e z1B2|X@56F8f2DkyScMh2k&?HH!n=TC5-awxuBP4HZb1~*23|f`Zz{zGKnjU?ClYX4 z7EhPvFnK@$sDB7?;X_^j&s&!&{n$SQR-Mhv)yAF7R~LWd84TRzUkUp84Yoi1l`ldIu*g0V{9=C@rA}Jh8}Z zbnFt3bMPO*XUv++W4X`nbjqbP)?BfIhShL7aQ@N-0^EB;!L5rooD2$FY-!Iq&|^QA zcS=kinq1=4NRlqjU6Di9@WB?*S6?7t5OAA_s>nJBcT~$}S2cMS77cQ_jWC9Q=_UAJ zJo|rX2Z+=k36ggle2gDAQVB{Js(O0sQibShZW$UR#98xv(pA%Eu$E3MyFbWomJ{ZfkNL1T<#4nt1Em&Hj|JJTU~`gByKMhB0Uq z5&zlC^eLlA%;lg_WZ^Yjo9NY>XhG@HS$ht*eWxG;P2#=ye~#t)RD@$6QFrkh+}@$a z*C(bE+G!Zs$3jaQhSB)aVQ_@)& z;vL!vGnoy+F;i{0zj+2VTA;UTFw}IZPh8%&QypIUHa^R z1(B9#h%UErz^V}UGM~{q+dk;1e4CUTpbzy|d;q_onWoI)KTF$gQ9JR}=ELA+HO@2f z#xG>shMMH17veCTpmW4Me&+{xET1l5q+9gmy>9k?g{t{)y##nY4=`S>k*Da`cw9PH z0gCu1nT1q3*@^h`Gn2cdwWhRcv9-gIL0@M#xVerE9d}>5QCM~7N`EN8Qv|P*jau@R zt(c&u{!}tip=vKN7rVF@2VR)G%OIESqr&W93|Fu!Bq+_=dH&=Ad*E|Ytc3>%QlRs- z$n1K`|126I1XqWW)y~&|*{e#Ei98kV!k)Nf`ZX)JvJz{y|Lk9mH+$ z|A7KE&tm^$3zrtqG$|{rmrG%vBjn)0aB^t((&VoP;7cFz_wA+atsAzrbbw&(^<7Kh zNTB>rF{aGLFZei2c1(FWx4Su=j92jH{afEKQCe9?1^aZ5eC2);7T})< z)a7Xs+x>!oh|58$e7Ux6e=3^@+vT65`5w!M1A-OE@cIT1`Ove21oPwF-WDy(uzPsd zGsO}&(#MWS$Lq(aKgR3p#iThb-)D1l#J_O#pbcMJdQ zoEpTej#!&&j>O4Zc znz;COVLdtkiU^5MK52)CiLaln2{c$?=IB^a(1RQbEF+wf;+cMJXtF^6up&NcpX z1P7?YG|uFwX4|A)o^NDc5cmKZ7}fw_Q-*@*i#s~$o5{sevge}-(=nVs+Z}^$2N=w5 zvb#$ot&OR3qC1u@MyCoY&LpLgv5$W7&z0vGP538O7Yw1FC_0L`L(9LnAzH5FTeAI( zX}kJa0_BSFPCi~Wkl(LDA{i;e>AXZe@4%>O>aZ+f53d-z!hwW2cUu!Df5BbsZWY|B zC1iEB^AjXizKT5};bur8K~I}q#f)o=`U@bzBH zF9D&MN031)d31p|6hk@QE&Tu(*5Y(-cWZ#Wm(o8R^J}z3i&b9NTTy{6KCM?Auv&%J zD+bE%dQTlpzbQDvjRgZ0itz&@7A&Cx`AWEUqaMu0T{X@28X4LBSdjms*h?G3HzeV_RUu$|=O*CsU$ zLB4`h=q9j0FGIgUTsvX9dx4qS6-XX#!Z{c7T^u)y#)e@YoIT^|+Bs)WMXc=Pfg*lf zes}fOX2m_9Dfj3b{Siol0}Mxdja@8}gVa6qKvQ?z$<5y`n3_m2m5S94%a^1I93 zLA}e)1|8UAzYTHgV=*zF?w!kEmCi?pqOc{>KFev+#TN01u##Y_XNfm2c7}(8fVY5S zuT?MzgA1bizy)IskZ%5tmSHDQ<2{;Vl-Pl$D4TR&eN=X}UpdIE38%96uyq-D#kvuQ zxy)He@-NAY=#F^kk_+lyScuTtxD5iau>22^#h`A#sOGSsgR#rrh~;@=3}#0hS+LXF zVwLu7hu(c80U3rp9F2YYX1nWR>X`U^Z7Q}U^ij(}jyT|wf&kp9HQo+Qc(>Y;(VTXI z6!rihuc0C2s$B*+^4+fVLNT22#*7KH#Q9RLVOc`dE8yfBmQMr>OU zI@vAjors=y47d@-0$emf^F-IS(}fn586Yo?9<5t_Av9J&y=o2#o4p6C85IVBWMr=Y z!)KYieONc$Ks!h5xc`HQ2;;<~-u915>v^L&k+F=`jn3^KFa>svx930sWxIF+)vh*5 z6DpVQI}A0PRd{w8icFXJC!7SwZx4P}6?KMw-PtOUl5Tc8mLex42Vh?iNDO%O*{tUS zCW^PA{+)5Aoz7R~2;nkkwqHXc`F#%bei^{-oB6+~iIzXpZ#Z>)9m;=>W?%8dHJYyEQP4?_=riHy<4B=Ed+5?*e(YQjU*KI zIJ=8-f9C+Wvw!_r;IDP*Iz{Exc#M6pq`#*tH%-P&pYgd-MrzG?3q^&PE<=nb+ zb39^Kje^7^%VM~&S}li4psm$#oDM95QbcEf@HLOM{?&CMvmh+nT2xQ)Le&YPiUUug zfIhljmJf#bo|+A>miQL;tM}d$`a5^^+SLc6^nK*PmuJhD;{a9wLh1Z<7C2y% zRiG_9GF)UZG?=b4Xk2sTD)e;!V#^ZEKX}kN2xY^4*P`&V*Fd3zf7jyAhS^Y5o%b{k zmKLdqtX6l+C>;9v=1c9^Xz}8A#*mfZrNjfZ8!~Lyl7yi`mA)~qR4dP!so!3CTkhAn z-K<0FWiYh}IC;ha1#J3&`Cz}O6xRCoMWFE1H;{>^jHhtIKIbhCOAHso{c6)Q1_+IJ zDhMt2WFjA$`*4aCDuC_+R&dsifp6 zkxpzo8~E~kmUpqUiMRuuw%B>s`jWO&IA_WpZ4_o4h5RFz@6TH3L`#P! zD%);N2f?eIISXst?=ixu=*&blQwofp)10V5A5?!e`jG$f@JReo=*&TF9bq2uZUpDU zf4#yWdA-9v=Tm0=g;>L7`CjgDp9P2a*sW!|ULk4y2mVv>7>|n=-6P}eiibQEaTw)v zR`s=5^m7n@0{HS$GTxt6{_6Ge?b8bvm4wT~o(?ER*-Sp{f->yk%8)*ELWQjj9T1`X zv&C$mkz~*Ca%(eXv^atxR!mvL%HS21mcgvl6u!~;oQjh8yvkhiDvg#QlHdmQ3d_AS^gcn(J7$`}rZB5pUov}lKS)X&Q1bGc<(-jSke9F>Mf zH-RM6cxb>6-09yE(r(XsjLIDmF>dLTFQL{6n(6hQr&S?ok@t$tZb@!vC*5z>DR<_I z(}^W4Jq3wmb2*n-2~BeiC1-EFV~r_!XdJ+iJ>dJf{#%gv*kh$NtKo58LE;4sE|-U4 zNY2RSSLMx4y5)^th(t|keT|f3>z94q-Wco7hYSoiamRk{U2VsOf7+3( zlOrRxnF7BZ#88PW-gSjuiJs1doc!>lqY zsfPxCN@moHQnFB?0dkR%Nm{B!YrhiBUOjBNM=u&lBDX81w~{umPkT@(bF(C4+TSbG6O@UcW0&cUB&z27 zlI4_1aCG)7fU4_Ws{r?0wC(Eg4Hl%_PU%sJx&LGSB!PhDN7&~(fmiR&Ms5yFi8&b< zr}?g?RUea&m>U)Q)f#STmEKH?xfCgcqXi(q zX5d{y0OPJ?MUCfk`TpP`JoZ*>X^{^PB)c5Cg}o52!lo4jBE#3|QK_H^e@1eg^Qe0f zWeizwPcG^3$s<;kJtHoUb|Phvly5UjY1(r}`kw-*<(}DWfm>Q)x&X%%CC!2(otFxK zQDws2ta*CN+lEeq+zcdwTyLsZ63J#sJoW1p^nD?m;`Zh#2gZ8Zb|T-C`MK1}o=krG zc(7+SZLgIIZ&K3i-G39U%|fc3+S^~KD}1W@N0l8M>zBsT+5QHwRfuNX$syJvT*dS z?)MAAi9#lQjkqP-Qw1KLmLA4%vYVu{cBdvwqdvSK3-oZQQ;t~$YH#b z)#PC3le)qo%S{5{d1rt9?p-pchg{p4%rzmbN%-?4VTXv1KwAW>CCtUx_Himyd)2@T z(9!bY%SkR-<3q^Yc=g$4x#~PeBdNQvx?#@;T<<>B$|*NNeyTbDG}=}!tDv1`1CMd- z%@>z_05M*zF$_)L{>T}X6+MBsm6pqwPDw@##h+L4nZK`=(mi8g{+&N!SNMm+ojmoMCzG0K`7~`R&vPfa($d*3 zw*qhJwcADM(4@t7_m~kDmX!2nKYTU9WEE8?y%kjNAl2KHw3}|9nMt6jU=%LWk>D*k zm)-XH@~8LBH^0;>z3E^xX$QM)ON?hkGK~MDONGGU4TbYD9%6l%otANEjr`eIu)Jqs zlRTnb%Q8ToQ!0=b<`J6H_K|XFpawdgU%)C7^A(C1n>`B`R5-uveGt^;lB#;O>(vOkQu7`z>@%0Hg_6238D&-A?jeaPbPPzJzg8 z2R~fYfhJD>xSMWxeyf*37U)ariJ#NO`YIwA$J5qAoca%(XRfnj4N3(U;DL!5i1E}5 z2fw7aKqI3w$2w}N)kArEf4Tnrg-=Jc7pN#yzNk|A)|wV;Jy@O+`(})9#|zr&3ux@r z9F$;8f&9x)1dTO+j%YWU8vF?*?!i`S1rp4NSea@$VAUk>jb7PPWvEyYu>B#8WoXJVf--U*%9d5!M-F;lE&f}H4Asr zdM+<5Ws#K^za*E9owV^;^u472p>hAKI5FPI!e1o#@B;9ze1HbKD|-fYf9jYem76z` z%D5#QBZKdR7(-@ymil65+s{~!sNlv5^EvNtoa+%Rhp0oMnDRMbv4j%*u*Vvb7{qg) znNnRG*NQwK^^OETP~w4XpHrgNy*XnfPwz_*98GvB_-SfLJMhaZQ09-XJr77yS_EMJ zt|BJ5lna`k>PZec%m&H_ttM5?9KI{%D zi*=jE0rM+|F+Yb(GSAYsEG2m`v;REMhBBbk@Fa-Zb{42mQWU7|cc2uuK&q>#h+t0G zek#L)DwtmZyi8soTN%J!ZnO}*feW53T&0<6nV(=l*-|>E`wyhW)e2rD+cLN?jKU9aAfc{%R43TyJxH+B&^}z zwmH{Z8EzJ;nAy%^dR*o*1wo&j=?dVv&~%%)!Lg~w;I=O4&nevXFHRZOF%_#JQP>&69pz$ zM9)=MfW&jHf%l6{jKuBCA8S&-x$&J0|hGqu_3tV8$Wd9iy#*3H0S%(=Ks z)IpLyc@y-HiY1JOuM^`_(GK`mwo3i*a9apA6r< z6TKx=xc22ww!YY2#*20$a@)85=HjtGhW7=n%%0zzuB&5S5vU|_k6B%CXKkf&@Hw_q zP?_RSD1PKT$K@$H4e}BA-dM{W<}h)ww&F95U=kNIlK;O>DRYWkcX+*C0M;DvT7m9G zAg}YGZ7A;(SC#aSkD_%Fj80Qg$8t;4AF4jyU8p=uR*BT5mN2=w>`G|#tF#4t*H?1r zX>V_vpZl*CHXPUF;zW%dVnMPQQ`#^V<`A3_Nw+{(Nx4eN8odpm64~MFoQCAD zFQ-H*nNIV08(B$=J#`&_7^zqf5zsr4;jUH>^h z0MgrF9{{mbPE61Z+e8fh{Dz)b==-u!*gFvRrx8WEKtg28Tr)eO&3$EP%mAiI>Zu3S zJz|!fw%&d$0MkxyJ2D$IO$xU5%-%`KjN7-i$xqQXQnc^w!VG=t?ke=sK3k>vq3@S$ z78`PCS$g;;EI+{XF_0>9^BObN_!}>z!%(8M+(8lpnE`|e7C9T(w_EHLj94f({6?+0 z+jP}L*x@4@absiOa5;Xx**=3R9lyO7@d;9D2pHjq#)7-=*fv!a(v^f3tK6tBn)z3X zN8;UU#3RRCYjmKBMS7xnwfEnLYoX7-j5!SatUC-kbog;Fq4kOob$4@w3(gD03-jiq z$znbG^h{$&Bu3DK)$cvQYc=z`iv@m2rt>e3W_?x7A<7Clt8}Z!&WPt9`O;rlZU<$~ z>YVDvo8L+|=-rR(-TNbQJCl<&u$3iD(o?RH-a|%?#ZsmSkqe(>X%c8F=c%u+JH7F& za_rqQRCTGZhnX-B|9|a30?{6(0ufMr4m9E-xW1mx|6@z`xdH5TJt61hcxUAvH4OKU{!cI@ z+Jlcn5xa${v*Pk2eU_{veY*nz!l&yA#s^W2m~ky+fMvHNczv`hLQuGoOyKM|Gy8l$ zMlA4P1B1vG?FFzOnC>+o{gFdj2?+p=f^>7Fd(avvE3ykMr-DxG4S!gS9V6P?y@*YL zqLK1p*bb~hG4?3u^dJWRWXB!DVY~|sh|nPujP1x{W?9?jb8ZSw)Z_sMiIT2WV z>l`t9l|MRd2_>If{|~E;)R6vJEKF`NdW3U60pASCJE_MeDBKCWH1B(hb;8IMly%Sh zM{IX>1|6*D7|)XKVVV0WOcgKba}mNo9usKq-CxODyepm?RO?(#XXR2OvmbN05Y}Sv zvd$&|+irl4%N+SR5aR_7+$HxIDbV^raE(YN|3z?}VwZf^d&=7^AQ49BBPz7NB{}{H zVND>qJme}=F_hQ^f&{vbfb`v4m z%V&~#{DV9{5O{C?|CuI8N!)R|XMu6G)g!=C{)vYix{H})Z+8kVKz+}Zu_r8?D(u8r z469(Hp3wCj2ymH;Q~sSC|1XO$drxH(R;<(DoNvq_0ybB9&knF->X)y9@`4(SeFCdT z)q+kw42rPq=-;IhINJ|%2)T*|0bsS-|K1@B(OXL`n24?hs)&6~ceI@LeRPYK``gfC zIQh+kH5&Vd6dBE>Os)Loc_ok0Jnin6@a^~i2l4)Qzks|KREz|8E)& zER{fD69jU_`){{m>u@Uwu44y`K(N2sY6>SY=k`ed2b}ZWQ7ClnKOXp-3_ZdH!;JjT zaKO6RffNi7O!->Qu9Go%XaM?!fIJY#v>9f}HzG@IQj|-zOQ`r5ubUGJg}i z($uMV4Qc+BvwuDV@Qi$W9V&b~JXBh&6rSSYKz`z{od>|4Kdv3bznLFo_$Sy9@%^BH z&_YvRvKs)vEc4*nxLwl)^iL=&z`(KclJ77(`DpphLM3QT{&Gj*l|NFxjR8fTFLx2B z1`oyVU#`Y-1|Qfuh&695hXr48RE5|cUmjeDzYoRiPnD1h3=sa`lvh)s#G%~)GTMb@ z(eCKoJ#fbu96UUUyjeC*gYvdFMKeB=}K zGI}|y3{y?Xr19ow_&zbGr2vs$AtMqC9A%=BqOx_6hoNaW2*91k%Fcg#hN$J}4GN^I`ZZsOBt z4^Yb|GrIBbF!=?~A%zHch3g+Jj>>QQM}(an`ticVaxpJKDrmWI#9ab_$+8%43!Y;D z^a#kXZUl87eq+YVilndnrWyUH^)mdbfZctflpt$0Ea`R%-u&L~L4p?rAfcc=rmO*T zM3+#K=FqM25eIK!FmniH>cH!00 zz`q_?s(QEIx`^D{)8Q|>R;onn%Srs`20=Jp#q>$I;3Yn+2u+N_0$SWEvd}!fYHx!0 z3Lg+sL)nyx3xV3d8IOVa?G?g*m#z9^W8ZFE{zL#s5du;n`##>{`R7AW+ad9MI{hV% zkr*E=+BIVgC-C`anaii<>EPZ7Flg=`YZPhTOT=UlKB)42QT`BPU~)|#99 zp0QmDBY|995Ukz!tgIt?Hy zBLrJGI5%$21G8Sq2waMo=Ui<<+#~Etj+W0Vls%=yc{qaWa=zVGEvDouQXhNU`}~Wf zPcZbLRd&_oSVwtUC|75bPp-niqesbp610$M$DaHTOQ46jajZoR4AUAuO zWJ*zfL{wW3znRoKY%~7So0?#PXj0xvlily|#g8mk6 zuVrP7rr-IM5|Nj?3Tx*5_BAXkjtseJ2S>)Yg93sMsVg8_Rd!GPrJYPFzj2L}Jq2oU z{X3_pP_NhGKHp+qhb@n3B)cwY%%iNg+PH`WQ=}?nDt$>JrH7XF7%1O){@LE!C$zdJ zdwwJ8lwmS^Z8 zji*d_VAdH%LioOw<)Wi7e}ftMzl& zDYwZszkBN`?(TB?RS}C&J9X0x8C|%znhPsgW7|poF<0t=FgrSi#-Wq-E(`_XTc#pi z3%ZMI(Qu_xil}Rc$%1KbUsUSD>2&qsL`&|CDg!z6%#GMgf5s9|v8PQx@0+^KaRuKD z&hdNMc}(=oz6!zC2qy-wFBW_ZbSpmi!r~@!-froLe%b74`?*ofdS=mQ^JJv=(V~@@ z{|2>D(Xk6~_?{{e3Oo4O9~Gu90^UCR1NyUD>bI-o#S6alg+350o?XrVLDl|tb|1TGD?X9`q%p$H+{!x;vM1M*vP4(kAA7-7>=Hb84hy9n;eh%b zb&KH@eBvM;9XMB~Y&6Rvq>}%RwNq!Y&?}cgVP0j}S6q$CjWMRxJDQ!p&)8_r1AG_U z=0Gjp^bMsOfio#S-asi1pDoyZq#?Q4zDWHU$(JgOiD~wRQ5gvdbMZk@xiMogTx^@QqDx-hTw~Kolg>;#DOI^g8Tq-y{54DILaYK_D*D-J z_@gnQK&Q?|(qVizWp-6O%?JCf_g*;;X7(vh#-I3rN5rZs{F9Awt42u-HFM2X+zs@!8B_E< zo%QxI|r4J>kt@`O=leMHYZsoiWNME7)JT=2N zhaf--oG>QR5(Wvl9^EudRUyRL*7_1g$z{j9uvI#MdHxf>wQk+znOADpyx0h!j7lVb z?O5;MC=XW zL$&7skIjMMl;SQg5Rku?so}NL-IO_ftbppoehdi!gCKuPU$z`X8%2k&RtZ1*_Q?h* zQMD@m!Glu!cl8dR;0jE~rC|u#=qDs>3T2ynoL7t|@ta3|=UB?|eo55##;?quW~jqW z7K5G3@y1=hlu5_klVXQ;@_#LCIlcokND$7qSxbTE9$>Fkk%T-Mr(W6SzFs{A2Y@bPf`cX^fcK;zQrA(#A%$Ck19k45pK zu=CTw6HWfxWNunYKu$kv^h0d?K<~T)rTwQ(kEm&Ez{>G>fh~?1HXfOJ0<TEGRPUo+)nq51<@}Spc*|qvbzVn_?1^3 zVk4b1AGh(GZSbwS#k(R4yfWH`Jp`zBwE3c^(kx~s@A`y|68TFtV%ZqlI|~dyM9-o> zyB;&3^TG>-fTNA#OXkic1k?5sYq!3VeN^W#%pq)TC~|Drlh{q2#SDa(=ulFg8DFc(oX+GDBaK4Yi`eCpqXVDJr{7e zK40RPKG+_eOHWu+Q_{^25NSgrsyw<5L_VziT(5S8!D@5lYmob0p5*XSjNu31O7?ff z6Eet&>lMH2)a{njIL6(sa3GA7Wq@xzT2hW>bMv(m^vu~peX>`Ysm{>G3^+$>`W+?U zFtL6GsWd0xE+pzr9NXR{rEK#bX7SompK3YoM6BYXpgg{;^(;brF653r62pp7Ym%m|Nan2;#GZ!2tPn zK;@_DYOKKS%{z!CRMA+y*BVKaEcD<^XCmIKO`O;rkR}OsbnWzj2R!)jtub}!vAT?f z7s0=dlHEb5IIcz8)t{Q@985nygUFkbe(<}w5<0jTL$DgIZcblhZ?!VyeTeF7W%<*D zBjfygcB7HI{*z1f<-7RFQ^)PtHlNkv(YvsPLzruc(2o?8$yA+cim^7um`~0aGcbFC zz7%CamolU`^g-CiJxVZ(*m{k4+iuNHBS^)~f$ug!=xx)``TVFb9h;McBP;n8d~;eJ z*m_Rf$MCxh4X@i9E8&kJv34Cb+SX@&0$isLjX0)_+P7rIhfn4jl7ol0hphUC0TAJ@ zyEJx?dn0h?QjL=IDDG$gzg2R=!&c4w^KaC~x%OKP3g6U#$t(MCdK@pHDdl(*;ROi( z?(mhZK0aytJQRP75|ycV=ZrU@^V?5S;m7jaI(ScPQ$*u+B@H3ESLVH@6(6J~KZ6Wc zJIKWq#As2I(T|ue6W;_Bp|yjaL4MaiaNPBMc)b>Uvbaw_y0?15`qC37iozjobMot} z77S%YpcV^YDgF*;b``!&gCoQ=cxg?H6%UAmc@aK;o z*Kd-4J2N`#kz_^uc=OQeaVy*H%}QlMg@mWSI@CzRZ|HN0R=;lgxF#a;nJA;J^Pt+P zF~xI}!TsRQ(xMrbLt$>uC`}<>ltdX1OhDzjpJya99w3OC!3wDSIa5i=h^5H@P6HiS z$rtJVwfzeX7bbTG6Zc)r+?~a{{7;;Js=Jx9>$^0>$6OwmTf-a=y`A8khQnM&uiaRa zx0Y4caagBU=Hg57WBgWT*5;(Id%QlgXM7T+uQZtl zpy*)*8R3UQ})#>wF+mmn{( z!NxUr*@349T-yk*mmoLZz_@pIk*Nr&p|aZj#+`yA&i3{bkGWgt>z1-MpUM%MSVN2D z(Pzf;6a*>d3rD@Ohmxd!fZJ)aOHApCU`Z18p(q(mg+HmAfL$)*g6_#nab+B{#I4qZ za0zJ!xfRblH!K)QYBjQQa19E@u|e4%KV)V@6)&_k;xbO3-^opAWfpqa723RN`RNzk z(;>sJZaY5xaUFMH?=bG)pv**UhSjp>HnG!Bhc9(z%zt*%p7Ot?`fc)cn@m*P_c9}s z=w<7hHP#OY+C@AO7Li2&e01&aRo)pFX51q<7bk&wwmyg8lOGix$1rF*L2MZ~vnpOt zxknX$_^4w^;8$*D*t4W|oBTb~(V|kA&WpxQ*1eW-W6#%*AtCkqx3~ z9YQCyFokNvdpt)Wb+E!bNlx5%I7yXeX|EQI%%!uMk}asMaxh;va$^;WZ!_YKSmu_F zsv*dunLfN?UN@0ED4OC^@`QXdxL=`{UJB}ZM4LY8a>2YF~rS;U1p3oV{m>uNC(6eewA|H=>ko0e!oz)$cTGA(^?~~v7`-k zG&2K=WGBs5G`6DdxN`f+=cv7s-S4mqfd3ez7YRpsbG`H2NQ~!CR8#dosAWB+cKE#rPfINyX!Eak$TN7LPH^K2pPU3Q(D?Z|D(*jqd@$ZXFL+KT z!%cy*d%PdT0f19~{qFZN<5sXe%RK-u$;9s`&jX60{vL1epHLs%n5)Qv2l_x+7=U$* zM^Qnb|4FTOo`);&D-cY*@>dTrjQMvYKMS--*av9k7&N~k?4=RZRrVJ?@u@2Y$j20t z;RWV+7!mEsxbA1SmdhZ&|3y$1jAnpQu@i@vrUJR?TM*EAFKvF@*3iM|UkoKH#ZOiO z+{&nUqfc3dI_96RJi`Y`|9nkN|NFIw4z+pY#0SO;WNAK8H#5x}gm{3@=|F;vE+L*c zo&qG8w|tpn-_jpJHmnoI`)1Zo#ef~MGr7yp_xk*gxj{U|shzZ*O&3Fwa82K7k!9R% zmX%YcI63x;>z{Mn!er!HZ_h$O;5^`7Of{G3P)Gt^x9E%^^lF{E$A4A2g`am*bN!DI zqr3k;|4nUO@2+aUlA69Ajgau)<3bcM7RXhrs*j&xQ*YhcsDS8z+4UA2%hbq5Y}so; zHRsR^XX6j><_A9f941y^S z#NJPsYGX2wx$s7I=N^-eS-d=-EI)Ag>BOQAVxsV9{cj&7#u_q;(qHbYWvnGOkCbht zu?e8en6?8B&SmfaR5o{uIM(`QSrV>4#BB2-7yi^Rem!S)lw=uzTpiu!M22MFNo|(b z?LOHPHNO#-X}It>>*cY_;7c3Lh5jGx9bRpiQTG3jthWxRa_QQKH=Ax0$xVuMBb|aY z0@7X5-QB5@(hbtxU9xFu>DV;V($e+ap7WgZKF|02mzaBI&6+i9R$LdoM@_9_oVxSe zm(oos}`m{C-yO(=3O{Z1ZW9T`nW(epzJ5U4l(#`AeFJ{HhyCo$f z9{E2DBQ@LZKWewsSuPRvZaF-qhM%{AQ_{yPq;)^y$sEpWJ#Tx4h?Gzn!Sfn+t+hBy zU!g&%Fka3?gP03Ze@&oJzcg)ZpwYOg1TbEWn*}N5nfHGlwetw|m-}E`aTjzbsy+Cf~ zM*Q%4_@^@^xwp0ROXCJ!>4zD?y@1(E{ zgoynG`YyjSwJM2Jsw^z@+?6%VAhBF+p#IT$Lsgll`N6E!%6Bh$^QWAaF|`kRp2M~^?^wk(AF2~OTk)bEeB5+h%w*iGU=jFg>+xBoOS8yGf!brKBih`n9_0q5*nwZQyLEL`h7RFM zy-3ay7YjmX`g(;iqasb2XTB}Ujo~h4y`YxT+2-0A@vu%MH?esUSlV5bAfjj5ury*; zFo~CKA=>bDHmswz)=L0RoyDHo+*&cfx8ItDnmW z*RmaB%weKM!vis{{%3Rq-c45g&$YCwnj(re&su$LQa{HXJ!e=>8~1O<;2ijD^1xGE zxW&IQNyZn?aLDWE+*0yV4;EpN-r~}xN3tA2>%j)+5NS882yn{&WsX^)-Rk@ka@>le zZLcGA?8+)FM_pKP0Wo&#*K|wYa)6E9lvuk%3d_DMvRTC#~B=<$I-aUE$2Hr*mUN znt_Y+O;Y1p=q=o3t$vAW^YatDPFu~siI$hv5U2iL(q%8Vtujq({+s_kRnW7+OpX%aaOo|_grrG9R2D_l)rP6C8g#MwO{9C?7KV$Y=TMvme6 zIv3Z*YR$(+mC2b8iwgkmy?0{8<*XMR%l)iP>``uCydq|LKG_3V(n2{kQ&flY!W5nF zPb((VVf9CMw1&)VV+Nj$S2S;S&s^^)raxwYBL!^=sl$`@oUBAWS7|<+&9#d+|#5`r~9o+E(O);e^I0&B`gKx4Xxe2f{U`k!EH%g2^9|PO^cRr^Vh_ z#0_IfCN}QXPsMAp#cy5>sI6q-f|*($L8|MSG`5{FXo|EJ3cRftg*eLTu`3-nZdShn z??d0;J%r51zsp{8zT$uXW-WD(8-_}Z;K2g;89;{?Y}|sib{lhn49$U~-QAhe#rQ1? zm44A7zg<|b(U(SbkCVuctW)TF0w{!~tIa=+S2KoCtK-!!Q@c>K+|=llj|M!FercGfmn55Z!!ZqDcLFc}{9~rRZ zk_88i&pKGEny+Ux=9U{&xn4qox>9DmGAX+P+H8{jout{DaLj(Ya zDLRS=v>0>hn3^Nb`|kWOhTCRS&toqga1C0E6UJHdDdrM<3EkW@@$J^@w9QhQGj8-+ zWcg%kkD%+h^yR{pn_n#wfj2vvS!fc)ZV6qy+L8ilnk~RjpQP)2D`Aik46>GGdtpdw z)((+T5${UyJL6mk;$V4!YxK&=g$l8c0b^6K*`O26W6L zfyx5km-U;dM$hErP!-@2zCQ8BT|=p2pg`3hoJ=O4dm%_yb%Vn6Km5|k z_|YS5P{UOgMsc}4*o8id=dAhuwl@zMM&?Ea3m)mXix_(^e?^QsLh>ECMD$2_FCnFn z@$p=8G#2O6S4nQ#rqQtHYxwq~>z+-hGA3hju+XhJrL{L!tX(yXIRM;Czs4`514di# z_Id2UdBsFwa~E!JO2+B$%pxX;M&%1t!rTY}h$(W?^| z^Pi;&iH3qlD6wC$DQUu!IL^T(Yrxq9x1@=7z}+*VTS*56QfqTzg{Wq&1^p&929zzq z7i)_}3FMXt<~t4Oi<$e!?Z=GeSXJ0j`d#~}gN3eqfGNtE(IyP#62g)E(qvSRx{55h zs&4HgH?!@>r2EihkC1$)W?H>d>}jaeMmCbbIQjAzHWo!kNA9aQ(9(v&Ea5%B8<8^? z`8aa+nQ@)(CG;DT2zf=7tlcfoK4P~$4py9$IaLsyW8v{j7E*KvgO4LUouUEb+lkM6;$izJPw<);;GdQL_F{T!cSaO3J)QZg|85@#)F zrPfv}_t_Ex@IvHm%1e?*t#V3$t`c+1FqRDQOH$M zLb4wl0nhHo_aK?~wOoxHR&Vg$1@|Cx`M+E1P9$#$acG-PyHYDUdaoy84bk{97!VGboSsnMu&^!5Vlr`rcaz~ucL$BbwrV;ri;WF93a?v2p7hx1 znOUvK#UP{79V7dZtIhPM7|5vQs*qz6_jES=;X7KbqD;4(0Zy0n{V)%FX9|8xm>UZ( zgeR4rT#sN^wHMx&hQpTq0i`V}ROE^1f0%#8umv5pmot?#f+ z4_JebKBA_pu|~ot+~8k4$y6zmp|P9 zE}-K~MlE3_B~obQG^kzLOwUiQJzUpwjbfXt#%pf9bWyz6F~e^JDcum;dx%bDtYg>M zZj)9%d{q}dwf*(-+aYmuwrwcsins;d@87x?T(u8_7r5K=efscqV`Sm|mTbKrHw&tT zA|74N*Xn=Sqd$;szi3E5g=}Tgr~18!n9blHy>3WwBzW^{I1_8`(7fwK<38@7ig#^G zb=3H~upk;&+Dh>qxh``@@#$ngGT6IRc!y3XO>8%<%pCodsbt&y>W6E?&0z``C5#^T zABWSoFqu2&25Q1%J?ES%6b&y1yI0T~&ph}N0{$PKd_;+oF+IeqX#cSt`UKYFtIP9{ zl=aep{k9ytrI}_zjf}DE2gWq(prQ>LFv;A<&R$)|`jGfR1wZl1y~ZX5_iwpvFObmtXJX+Exq zFEwXm9tiQ*l#NKQVfvEw~P+P9$X? z{pHjTWM{b%g4&dF>_9E>J%^7YHT_N9#ODam&^G~deT(PrJpE{z71{w2kh|kd#Ov+9 z*N`HKb0&|!AioR}uT>YsA7V2d5EyS|$#X!}O48=^T|)?c<3Xfg${ezx^l7Me*8|~Y z9b5FT07-_Dy#qZebfd!ATNJ*gd-cBme91t3sZMATfA|IHWNk?-z}j3N)D6cE z#fGYmWFF@yMGOS?Q0J&?R9xTyF{K`K?df>)>f4y+_inoe7s_vq_p`mk=k@%(s)s~Z z!yeVY(z4f!RmSRC@el?)oZz^}Cu-|^#>loR^+N1w-ob&e$10GzzYCCsR*@q}wmB+# zARPJ){aQJ?>!_+1zHi)+%vXY5H%gjB6TZ@roJ;L(Sz2y zT0%h@x;hfUH?E2G4Yj|6>;#BCGr(lG^jLvkEyAQpaSe%g*%j#!=GB82W)f>YpnW2o z0a-6xS2Pa(b&RIYeq0NuPLmAenUY3mD&cr-ho#x?xud08l9hcs?yFionY>eRQ2zaP zD3%NkcG%ys`gsR`t$T&n)>vwr;YAF4L7Qw*<;vWBk4nXC=s{YMlGnE?H613P+$`7` zXyloc;*wSd_rbSrReUwN8L2f%*&yY0;9=mCnK!^+%-9 zQG-*FL-)oEMyGQ-O(V61P}EqI^UfAho`y5n*0zTm|2Oluh0Lc*;3Y(%H>l^*m7WPN zwa#8GcT5)txs`BeosGMGUbbpnoov)B1O*`PAb~TIUu>2EAY}B2a4MY^czvQS+c%3? zD(!D6UDK`c7aTDis32C7bMNsSB_UkDAKlB0Q%~d5FRd+1`x|X(5-OBeURwJwma{7! zKv5lZuqb)HA<`n2wTYr_>Iaj1%sw-uDo zRgC<(at=cpYX}EP^jw8e#+jkpVI%c-+p4CR&qzr?|5=Er=U9z2N7d;6a{}_r3 zqP@j4J@gB{1dsSF4=QUQKD?R)I@aG~I+(`sutcsO6#*xtF=oB+bv*T|oa!m$cdPN; zTn*{IxJ+`Bx^LaWn9rXFcelU4uMoF~P8NB0MYGRLTtPW2|3euXQ>J}RlmxmC4+z;%>t=bXW(Di5w#+eCV*$jCE z=cym*iK=eW@-ehlw}b42uxMY``8tP-o7JoF>3DDaiK)B^V8va#zOT6RWg(Q_^np|N zr7N=aT5_42p??#=^S#0=5TsGvf2L!cWhd?J>szufS14OzfU99XtL#gBwIfxiG|b`g z18s$EOI@blLg1(;Bq3EbMJ@jeX$ec!ZdtT1D-QLb%OK{VbnF$v{K#3Q1vXFD6gpdu zsU)cwU7-`~M}>y;9ZXx$r8xek;wYta;N={TwYUYMCTuZ_{V*TTfEjvoAb{q`*Qyyn zo29cn_)*I^tL1c9Vrkwd65EhvY+~sUwK}1z$|D)*&h#xkM|E)b(+JzB>>#rP$eV)7 zYwiL2rSrZo^el!)tyiOcS51?{_5-=itHMmuDA+gTGaKEAS+{BKY4Sz)jk%;$(yoFf zovwL(iUeN_82Zad`(pr#F?}=)IzITv*%iq%oosqR)@V7r7){zsiF33qvwg&78)4c? zLVH^!XU7O#K45L%MZC_2p&-ofhS1ts0-F)&r-R-rw647_n#U;MZ>Ke)RH3G%}#C zY|tB}>T>A-5dgs+I}Hb@3ZUPM$(3JB)6b>FfST=A+ep)s@o~;!q2m;-yT-AL0w61N zhO7^uSsuX99B#efW}9%=ZV};x%}3_c^;w|`YGv9(w@&b6=nlwmE8u^<{HnYen@*93 z!()-B?)&?z&WC9!LZA!L@bCl4hr1=#{Hl1zr~J1(Gc|WjU!&z-Lj2bSd15W8oMEYp z7KrQns{EDha(W$AjfXdRPAGxWxf(!;GlwEGblRbIH;yy!_(Ms{_-35cL_O@)q~y#G z8-_X-mMBC5vu+=SaO-Ga&quPjaCm9{0y=R9>kqeLN`T;l^Hk^hqg1zJr`+VVZZ+dG zUN)%hclKIQc}nacXwv(|)r(DWBl=^jQ-{{O)N7_&s?Aq11%uKzz1JD0Pd0JLJJ$we zm8UsW_@yhumA3@v74o;gI}Qy`NvGTuv-~pdCsCboCH7I=cNPb~qs_P(n&K|NDD++} zDGeIR2g0H5mbRD2ziOx@Hh$!PjW3H}TcIRX(BrI+v34=R-)i0E(vNLtz;c``?3I_H zJ=!>77td2|A&_>YfC?6N?SABfDA}V&v2s!`W2>s-r3w_SxH2ZD9@^G?%3!hHtaOB& zmmK0nFl*{vIQKMcdCQtgd>H0p9f_XlWAqaIEZNQh;}$cL*n-BSTx=GV z>%)=P_$Y^8uiG@2ng$YMZVmy8M8pV&eXPn(g>CwzN|Jx`Prc2XMP}PH;98YFHw;a! zBe{yNTgL>-{R*a32b;!9A#Pw% zE(JgyAftN{`d_-jrE?tdK`m?RA$IqSig)VmdEuRZcz>0JHZ|j zsvIwKEb=Oyf%FQDb!Vch>(Gy;q7rLN9%E;kmLlkbBf*0H>0@hDccig_=4B>FYhz2c zb$44J`Q6>ba1C>y)gk^{JO_^hx!RKwscXqmIGWX2nrL=K#PtqKrR%=&mJ~_`_m%Ni0dY2i2Dd z08aXtC9Bs0oWy3Td2RBes=nM7-V7T+mv^t%|L@ov8s6 zLk`Dz|8b>`=FNw!pL%MkwNyPTZH@G!TQ2ouZphXOE9GT(87h7wE2xzCzCNBw2{J$89uaZ4YGw2(8QOuXP#11gC<;46olTDP5hp7`M*+Yn62>-79t|cTGZ_X*`QAm(7SVKE@spHO4}07}ZU5 z+zXxJ`S~>;*InkW@2+Ig9-WBMdMCWEJ$1-P$2~sf?rS7=ILm=Qw#{{|np+GLQDss` zeqyJsjbH181~wz~t@djkuVsvXjr*KfXVb&!us!YdRtz(CJ~$c-_t%RR6W|+_Tx{JR zUV5Bo)^pAHwOkn)l;sCere8OYe;?q>IM)pjLVrD{9X$d-)U6qjWj+RJ3qRd?Ov-8R zwSs|QV^nt3@?%5A8=-O*LWE}2IJ%CjLL&*6ed@Y(pZe}cLiUsbQab1ZZ_Yr&z>rRD z1X-~sE#C^=3qy!$_dy3p@ghx_8ahZP*<}E~WxA;U?v6T_Fnh|V^upn@Ue=v2>GJN! z_LD`lN>Vbk_c3RE12_+3m^;G+(!!-Xvqz5NOMI;joBKM{)^_BSFw_eg!zY7xN+Q|hh(T{#)Mqj?8bU&Q@P z3oQ2{C1I*^y!8+dxa)US`(poEha6>^0!lirGl=<`5E<6`W3f6+4Mhp)XUeW68$g|h z$Bb<(Iqx{tObG_fiNY;(zHoX@PIsRGis+f=h?m#lV(ynw%u-1y#X6fYn6j#8N0j`{ zKHxo<6s&&Fj}}8X21T!a!ki@S*1J~1slM!**|HJpuzCKkS98ENK9K!*6ZiCZ2@~;e ztzC7l25MOTdile3fZAAgZ(CIu>n@2l{k_e|WxD-{B;M2WK3^*>38pa`LPo*{;;brV zHYN`GVc`w~yCI;v1t#4w`L>}BG7KcRBcb=djcOzYjRvo3s4p4*m!xiODmO$d-R*^7{VlS!lz7O39hHfF9FQrMMZQeT%=X z=bMR1Y{jBOBGn%DFdz5IH~XhtU{K$lh&!&Vj z=#n{3F<7Sm^g@D*zAqugTN7sMZZ#ej`Y_Fj-fs>{9`mT>^<8^g%HU2~(=y=Qg4@(+w z1LyvI16#ALhCN-6^Zl9r(~U6)Cx#6n%1NuH_oE%q9A@plEd{)et^K9QLfU~B+}+W) z-vF-{=`X&^+2{@Y${tI(8h2Z}+Q_03Fa3Yy_Piwgpev8&JaNJl39(v_M{yb|=aCY9L zR(hdDK5@}Wzl=x+&xxx_V7hsqmyV`q*S9hv z;iA0;NHEn}=8VPmR23sX1bCaPs(=N5gJVOLMucb)J&GBGa!R>hT~%juMt=q1&{r*W zQ~|Ye%|6*ZQ?*OrIqEV#UTmziD_rl(z4&Oi#9rE=Pce-OcWH_De3Mq|UkS4e2%3*s zJmJ@eKzuim(~-gLEPrCYhKRf^08Z*#n}Jp?)-fAg-?QOrq~-`ZH3Dl7YNH{2nmZ|{_E13uR$(69L&;rK1A@@5RU6{)?|Cd-GP(ac4m3(dN zup&1eEGUbP^Y1PZOl3|yEu>^W!@GF@pU542NEMl&L4Y$^1jq3&I)kNI+0T_pTL9`T z*P>c~0=ltGF15Krd^97KT;|jpb4wSTR-Iu-+-7Jvzc3Ouzoeg8bcS1F-NMV79yLjT zHpd3hRCh}(sx+D2UIqYy5f0uQbM$1BW8RpI4v{pL{?z+Qs>rA;s*RUchNnn(C`h+y zSp?Y~sY}}7E;;9gS1VG=G>4_-oI|!~0D6UMS4D4H^-5Zpfm|^;|NepIFZ7cYK2Hl+ z$A_HHBlvRs$~L8U$7g~>l0lG4X3W$a2}T?8e$uP;_pa;Lv_Y`m3q+?gM zwLxvcKN@?O>e|mpL%FyYVw>EMjq-bb82HZNW{l3ea(!vF+5MxLF#OpV8g40XFp1hi zZ)0pVt!{sZfUI3?LGyk~&5cuP$&JZH7vJ^kYN5qHS(0;Uln~-fpX^GE_{5LCTeFWZ zC;D(^vOsMSn$hr#r9HqZ0YBJjnH+|N0Jy=4ol@6`GuO;*lslQ@Zal5ixZsSKN#GqQ z@prZ-`GfE;mCeqHYWoq9LiK2C254g-s4Aji=NL&foPVy?|7JCsfU!@l-i}4B(l@!* zX|k|1;UQq#Ou#m2Q{z^YXeE3I=A``VIp8b#6=qCePzZ00! z=lcTshs@;XI9?CBZ-xY+rV}hD)G7>YR>4SIk9t3!hxK{Qk)`j_Wh!F$A72jK&5 z_Sg5el!d11KT<6--9GM6gli`ag`r+66Mu(D@SRZGv4*sf*v8GeoaKRZ-Q!${#fc+= zFDYb<#`$^XzAnnOiWJSVy5Et!klT{YXjJGQz)3?QnmEdhth80_Q^nJt=W|BlRBr6> zc|1FzR;%>h{FWj~y;&(sR)|OejriM!vg9*wbr$B4V2Dg)mt3#;=a4SJ!~N|@8OI)R z1;T^g0e;mNuB2=q6u<29jYR*u8wtD!PV^;!uTM*NRsvV`QrH%FWtT|KtTqo#{AFdPPNG&9j%*X;2sBl;v}ps z%x?@h9eV0}Kazcv{WM1lhB|}b^l=haF;rQxz*h!^#;+`Rc|*nm<^7ocs=CAmorC~U z4}>iq_?r8@`lrXo`1`xxY1yy*1Q62yGfQ&N8Y*z0faxKj-84;s?|D`sy}fB07X!#T z<`Lw>4LhEPH}D`qAk%~>dNUfpuij~WGfpn`G62(G>MGSR{r~xsH>wp zqEPPttPUCEA%>4@xV(J*&Ms^1eyxHHet^*f^XY>2X6kgNb1f*q_P=Jmq#4jcU{{iM zwB>96V12G1B#V}wsl3;4i5}e4jgj$u&0qRv>NCqrfW%~R`#(aNRVbY-r~^Sa9i8DS z6Ggu*<&`$O#;8nzZ8%hjsqF22sv)LC_Mz!hSvYHdl)>LmfF63#t^^fY_(!g@(PHNa zAiMEV#1v~Coh`}4(evO;8vIO6!3I$-OZwj-DEW)1Z1x7jw*}J#aQ2}v;94lTfyw+q zt@!Ydu-eGy)V9QcrtLsa1m1lQ)rI`nNwe1~CTxge>tmPzQl&kwuPT!DfF>0gLn_A{chFMOux+hGsQSQ_zY&hk!UGV#Q6{4SH&rfkm*jVF~xq#`bciyET3k*7!wwtr#M zKV8U;o2aq1io#F)qc`sGPPY20FOMu*!&M4!pWd25tSba=50!Sc%@!Mn@LS)v*1=p_ zBeabSyv;oGLZ1q1C*`fU|1jji*Zl@lnwAX8LyXvh7=1ddSrT=`!6RZisji8u99D8# z7=i5%OVw~iFO|_O*8)bxZ@)0uxhG$Ze~tyIC^%D%Fh(Hw1vPa)@NwhxD{`3BCK19L z1z7x}@NIBnvgctNQqub?L6&$vPp?Q88X@%hxN)5$Ho8@4v^Uz z5|}CfVfVQ#zIJ+yh_9D1E97NT<%+9juk9?cR;sxK2h&*IydV?Dp~TEMBIH$pf5-`y zD2#CP`xTg-8A@VT&d1&h65*8!6MOXi*$KdsOhq43rmbbSLG$+&8^@tz`yG&2AhMp*c5t zT(_YDGf-OV)dwA0Msb+N6jsE%DnOtS*N5*{qoo-_?k2!v^Ci6~@;i{T@NN>OhoZ9D z37ofU#cv39>8wBYo)rxWQ}_|F6M;`vo@~(s+5feJm|w#wB&yh619aB!O_oO5s###O zaoUy5rArEnJW6V3+$NnQggMlGzfU_$^s*Y4{2%}j#bGKfQggmPg6lD~{(i5bo)BM4 zg}E*~3x4o=D$^Okk(b8?=lncp50Q6g7cHlc9&Ve^NTeZ`?b9%NC&M*CZTTMKU>R4# zz7G6Mgza+lsUp4oG9TAGg-$}lUnZ>$?iKX@-s0Z*)%Lz#Uh{pOG0Sf1Ap-BY5KCcu z)HA)K=OwEtK`*t@V0FiJfc8T%MyAlk#mJ4zx>`BIVDGWb%=D^1iTnsv{awD+SHaDa zafU6{P&e&oH~%${b&k}(uQ4X1_2+8**(Nw+fSOtUMp~;Sm++Guy2xM<`6+~Due3MV zF-G}ulOHhe!#zy_w1yG2jephI^FUFmD^^M#obxx{3mKGHJA#>f>j=AGbaQ$Z)DJNQ zY2cS3*|wBW&j0kU56uc3z3~`GzH~+)kc~ojG@Z}2FlYTp>Im+FCEc(bely} zWinIEBk!08UyTN0PJw@!)NBo{(o}4@c?W)<;f+iTZ)P|(Tq=s~)Tf1ZR+h#HR=@Z^ zNvWIO=*pR{^CF`iFhf>BIxXZZ4-wxL@ER8|3St-Zti52algOr`e@q?(-C;i{&{@Do zqG&%sr=?ME)3REnm)zh{~XEnO}wAegN>ms z4?@j^hReqVKo6_ai?GDs>3<{zykq|i1u&&n6KuW!`-EJUGOYOzay7&t4FB&Ss^raV zL3v)taBdHj3v33g&=!&h3~F6-%W2I&h%KXk+~J!o+WTE{cwrha*e5`k<3}I8pC}?* zwaw{N?cW;pmB8@u&JM>lP3kklox%igy)L+~x5=t3-H)QPjV^A5hPRv}!x**E0CW;0 z!2NLYyD5R6IfV6w%DED3MU~Mggo|AV3&KK&ev&7nosd^jDV+TNpW*i}MNwf_N|1)s zk!H`P!)mF8_iGtpl4DvSCDBa;hQ#7MO!mfYOXV!aSuku;Bv3mUAb|`6KawZNqnOBV z)MsebOe$KFRPn7CEOLHl!g(NflEk`K zIui&yI&N<}PG1Wo*`@QxfZ-ZrZQC=puh|ua|Jt!XAJJ8X&j`&+K=jQ8&{1cnU78E| z-!C_&X{)wt2W)Y-SnxLcvt;TxP?lY5R(>pC9mplHAw_VrYO@(fn|m_rA%?kdPAOYs zC25h(6xVk>4+gbOMDI_lyQ>l%FaEiB|7<0&5KpB@Z3|bgsyxzc3N;Qo%dCX^U_W)? zD$tXQs3K11Q@x8_S7`Z$aSK_}HS2C)M_d{pQGqGyrA@ z!_k?XO6zYZGBdchdN+3){NVTD0}s3NaBzAj-Y*Zas240dQRQ}&&^r8XLDi?E&c_|y zr-$*XvsI5_8&s5&5tm|11dt#`#9pr?i>@pJXzm(l5XG`3Kj= zgYoH*#)u4@u$Z$Cd;u12ing0IaFLXLSLLv`9ZP&M&H$ZG`#Dz!gb$u(+;tEdfu;w2 zZTbm%?mqWr{&=tYpl3CZnmOAf*vYK=!9=0n zQW)5#(ds6EA%^SN-u=McLPCl(c#os5%=xis>ID;yb)B~zM+Kh+w6YdL%2Xzqs`u@r z2shuk==*A#fuRdtmRi7IfIoj8^^%Bx(32e&%1OJ+wLAjo9h~(OkvbdZ)m0oqdLol!rcIE1+qNq4mM)mNqY^Y&9cz9ZIQx-R|WW4-IQ+1Os3-_0~;XLv>92jZl< zcSke=(ijG^H3C}dnne_%QLl!{E9(@h=_#OfVm+J*Rf9=7-BOZAaa@OPi(^GW@6Q4wVYVsy;Ba0eX ztXQGzXkvp*4Kq~_W~ry+W5qkw^atlZct^)1O)c?jq*biUOwHZt3Op0;uxP`oQHiAF zne#vGbD$w;hSDE1N0`1vUAdm|XaU9CH|0?;sG*L<4ReW6zLt8Ca=~+uG)4)KVxN?o z_(A~)EUYaN{bz zC6T97#)pxJ$e}cr^n*|qiApzf)u_EWWb^!=%(jYuB`^7z> zpZ0Nv7@TgUiI>8cq+eOuj2=##GzXQ;XIPj1JmiVkucgW(;~wRcU*-wg{H&Ygi&2ed z2zj+c%xupmto zOIPRcy6%TtD7TGO;h9S@x|&(zaC29Nsux+5!?izDV)EP{Y zrRy~u@GBOaHM_kL5D4n?r^o}c)fA;0WDW)kLinPrU*+d_HrZXE1H_YHAoBsE>$Ls( zTo4y$EmibyG{=)5o4otRSh2gE-0e}>E2LeNwZIT(uByGuZ8k7^p>c0$eib0dERASJQKH^595 zDVy4}Kr=TCxT>j=*HVEdVvHfspF2q`;9RUkRVA6vHbW-d=2LDn{czBRuUc9$O?as! zy{)?p$BGG#VVwc9O7<9T>IwG>2kbkw2Mq=Ebuh;tP|GHqHEr(JScdTD^i!%syx}1u zlVMWN<4oxzq!W~7O0?@DhQi~#G_etROD*O{-{CLjH@L(u#n`r+{_pDTD4={T_W5dL zT(25iMl1w9sT$c!suQ9n)@olUsik?!sCD3J9Z3h!({~-EbC0Va{=e&FwhDOtTrc+( zE?K_%7b3Y-52-Q4QFXh48c_P@#@~B_=)mfA6XjaGl33JF(EfV`y}Kd%+EndWqU-IP zIZNEAGj~XBBxnxwI(6bhg*vU`N8f>U10+q{|Naxt9^%UwdT27(pDP}cJ^JBUHsB&N z?b&O~X))=&x-tf~h!N3a&&FQBf9=&j+n%N48mykEj1vCX;9OfS?brcoA^}f?@27xx zR=nl;ZzfHhcp6WWfNpevt0{{p;SbbiOCX4rf!$wap@AClI-I7UbuHKgyleI^nW%UFwxAz^;4>MWd%%VM>~}9u9Vj2JWVhc zGx@jaBq$CQsx+pl@3-tz`|0QKL{I_o0O%!)|EC)-5ptCam>{Liqf^SWoGTK!CR+8M zm2=6N@|Ys5!~!r=Yx4|JGT-sfOiDP39Ni}=&G|L~SYH1%c_oY!!-~U|PGm-fGr`l& z-osT6;X>_qYWXqPb6F580E5>W9xV7DJqNJ%*3j_r41JHfD4~Y7{~iqBWx!DfieL!m z*C@)OeSrGvb?cSlAfp(uTmA46DI3Jnx?U>Mf<3R9qbI?efam9{(NEqh!#k+ ze32LLIiFZ}qI3}j5ZIhcLUM%pt^tOz|JyEXpz>iGcP*bhl%FAgjV0OlczF7>_79&B z05A`L)Ba;7=%Eb05BRk1LeB2b4nB93S!3y!TNpC-u^2z~Bubly~nPh6ugD1{qq zfz$nk$eV*>xS`6(``>HHf}mH&sTUO9<&ZKD_sQw#CK0$E9f=J&eXw^N?FuDn<3yfy z$^?z={*@Xv?ZCdwLf6ZO*l*|Z6a#U$MFi?|IaFbFy{QDcNji29&1>a|v5f=_%?nnD?iDl3;i799aSU&p}9439$Sc+ABjbbEVz$8=igo;SI)H#8>tcN38BD zMo#c7E#Jw0970gtmRN{pY~9)w=!hbW?ANb=L}GDP)x5J|1`=+7nHEPBn@8%^=_xvX0SZLn`m?7mQS9cjo>r*55V(1HV1%zIZ{I?Q~mxFD7PVO23lTvNX zHw~R$e}fTPE}<;9dLP+OL-mCD&)kHOGzY^8XqBkY7bm1PCN**N%q9!r(X(~*T&bnd z5x`6%&z$XO)m5I?$E5C`HIMLGam$4cn#3kZHjb9>k0_O%-22wNcW=wIDP>5UIy^A* z8*YF3_2*1WyGN0#8o`m{C`*+9eKr2S7V{j9?FlEFugRq7r?%8l5+mWK9Qy>bMvLZt zS54t}7lVixgM4sD-??;%7rMe!u19V0ol48poa~PQ2xE4E#@L@ruGuj07Md8lNOg3X z+VmevrIKo9v)D}R8J!qtl&0{Cg>6LM_;Bjqni_EVlxf>Ov{?{*i(4dP6^difKl$S? z{m0J0!`TJ<)dP$MTN1Vd?BFrcouGT zOhg6DSl%x3GgOcw@Rp9O4DC6yLT%|G(Olev@1Of5B}#k9buBYhb6)Kbi7Q4Tq#zj% z7rcu%j#|%>2oR`{U#CBB5@_wg1N&gmLbp96XtrF;Nj$pjiT}$|Ya&q5(-B}8B7gY) z>m?7)TbRZODe0#`8X3*7tuB0DCsC}hpZ8CpgQCWdbAAJ}wuE>0nBWX2?;2mY=;v0_ z>OX0Sq^7wqc^7SG%)2kaKy#@;sc3XmaAF^+aR73!ZNeEhC5|0iv~E4Kua1?(4unp< z8%vXxclcYr_^KcKl`a0Agk5eeL?bi(^%Lwe@ltYg^RpBGJp${sJm3iZdl~I4t}W#| z;Ms*@E*8j8J4X{5vgV*o7*d3dVfDeRV-nfRkmQuDJ4EJj!b3W{_W(rUmkH@7yp)H zs_FI5?NHMlgyxfHD?t#RNwR5U#4D2t)_q!wWbQ&g=E)3yVm1SdS^#-X$#s73+%24p z1n%F>-XvTrCI6I@H=|0bo7Ar&gA+AOtWj{$^#((?48~ZYmG!+GGYMJe_aG+1;03%< zf|is%tVLmNDX9V-HAxgD#B8|~8zBWNKAEHGfF2c+qI3z?t~FOSW-Q7 z_+trWOBMwH#U8~Rdsbf%36s4@pQAyi$*g{s!9LBPNbMR7Ksmki93LL>@E**Re9=EL zl7wix*T`Ur$#X355^6i=z-%h%`-==>{Krj!ptI>6C}>m$e(1q_WGH~;K*F%rSK$_4 z@n}q4?f((;F4hJS7KX+>b!g>-W&pZ@&eLr?*!urOYz?QtA%MeX`MF$1GLiI?=+I&s z^Bx0c@0a%u6@=Km&|GP?+MY8bD``7J=}Lk%S?xV}E1Ay9rnmhZ%DdIiNHDP}N5h>u zpXsVQj|49dXllvjbQjR+nfE_(wi$zMkn^N%?C5GFyaGK^>vBWvnV=+8Q)m;Gi-o^o z^r=X1cPzCQ1En}**y&yrP6E@F4mfnIe`Z3B+hoH8-7|UJ+!sOCj`Z(Qs{mMMDZ&aj zLj`f*FQ~csaNa&axUQamIcC065p@!J>r`KMX!6Fo$W`sxD_fhY>ewMY@-MLdq2h#U z?;T$PL{AO6L&*e2Wiok|m~`Hl=gSv5uJzDg2@cT@l^NW9;s^7Hy;8SjnVZb< zMGP~8{~vpA9TsKR^$nkcAl(W|h)PKd5()w;B`w_&O2g0{gGvYpN`nYUH%P}2qX;NN zh%^i(-Q5H8om}cA-uLtV{l3R{Jb!X9=h|zp+UvLW+Iw4bPbfNi==;?a>b2MsF#F^? zEV1=gtyV!T@gf!W3|TCe$wA||S-RBV`I$QqyyhSq9)}?G?fG}jhk}@Xam2YvK+TcE zD6k4d?VsLR*V@HAyNn$#6WnQ;Xp;jeO8n3iC@5RAL~1#5ZMG@R_qoJXxs-i!2sG2C z>np<`*rD(fd?XVS*mHXh4`f#JgKIk;3DwuW1gXYoKz^hzCBn(tKvzuCA?$Q2a%zXClEUZ*yxH3nVwH?2O_YjKen5Uiv` zJ;f8XpDs>>7y;k=? zn$9BM3L2s%o683!y&=CCn*L+=8A`1Te4jO2BG4R+Ii3=NNzo2^_D2uqiid+Bt*ZT( zcPNYpqWbqj5AlZsj%FvuV5HcC#0~99#0=ilO=ndwd% zn_-Qz>N3qQ1f9$;GY@$7Ux3Qfe5rVkf+x~nU|Ik{!Ddh2B43qbma`kzOoBIT!nHOTEV`Z?7g*xDNOp*4hiW9d78y0^ej?)x2L&4%v(8x7^ z>n`bYIXhEw>Zo?ERh-*viT=b`-bj7zSZ-8Yi0=ZOpB8vo)X!z*G;Qy|*@q26opQl* z=^ofGHGAAUbmX}v+YP;%7fUNf`9NU80+xS%f>sc3e-60!if$ivvH1PUQyphnxnuA~ zPEHs7HWqM;)lJ9pq;faJQpc5dCrJcvJy`PC$cEbV=}J}0Um4};u;1{Y_7hqyz|t#< zulz35{cN{}9+?))ishHfqUa;~d+|;DK1!b*_-QY(t_LNga>}2m2l}A;F&TT~`yV*2 z@(zdbdSpfpmL-$@qx`>J?G!RBllrTSJ@7N{oOvfg-x}`7E09$pg33&XPW{IZQNA~( z;nR+lNxS6r{p@?q_vm;H@YcZ>xXwsP{h&hLe6c{kv#dv~RvCN(`!7`uNgs^f^K;Q! z=tU>;vuA#cOV@r$%PfC zA1s*vu{p3{L5uf+^HzFJ@PV2bG;9+d03e6KQ;#AvK|?oeG+kASTCh;X73cbL zIfaIoC?E07o&$l3&C(h813*QsXAu2H)ef%&)-4Q=RbmPRR3{=8lMA8f|q^zYI#w#E;k%FAmN2S z*fpA?kva6>?WVE1O$n3_Te0Xq1Lmc@wUeSERhjbVvCvFsMZuQ{49JDJyHt~}AHB%5IU7a9M9BC+FbczF)-hHxD3Ttn0x z=Tk10Kigu@6|7E6b+e7u>3bZLmuiLQLt=xb}A)*IIY1!Az7Y13RK0fup6EM<4fD-VrKye z7|Rm${N#tEW!X#<8q%;XVG(KKo;CVgg!bI>hpe(?nNR%ITn=xgT+k*wJ70Z$-xc{M zdj43bett=8Wz$Xc{NTXc=3>(7m;Z_@2QymDI6D!DoaHJv zOgY)zOMw~to*a$)n&9?RZjdD{&c9CW){Nk=-4=Rm%2>^;<8^|NJ!{H$($U&5*m0{k zjCP|7hHfLMi`9SJ7}d~q2Q~X2LY;2jT;iLm!5kh};rn8!iJ$iuUW+RpTF|KaMz)^n zys3JGpuIxP30`{eCwlNi8|pFijX!?2gsig*)Ng=hgQvy|)y)`_|4Sox416`%W*8dL zuFnlm-jsUJ+_o$3n5hw&k+|fznkmX)7nc&E-pQ&UKEKVy!_9$@s{I4xPTeAEX5d(_ zEd}QFEF}}|R`ry-3l)4=lEa45>hH}f{*vorXm&zhxgs{tv{kPzbGA1)oM z8*}X1#FC&85UZ2eHpsd5lzh4OD__Ucg}e|MEL7X8^RWKwqUI=(|D;YiV~*Y%7&qKK zrG7k6L%e?;3zhS3S|D@gZHq;b<-6I~a;;T6)sjXQ;VzG~h`tX|U@E1uLc)yC zRfO2Ho++5KxxloS$zK+)>01$PUJfJF{q)u8-CBRmT^Q@f=gHyN)usa%ec?uwX@$A7 zRd4969UIluzkAHqmgxn6e%|0(-O-sNR=?UWFs{(1^m%6JKI;+IyPgT=clR7SHlF1M2sX7;q6IId$yw{P-WfoJNGIH#mSZ!}f%NZ?MW?O=glOCsVF@7C z$s!n+KE~Ks1SH7n6MuM=*R4OWT!l?_HVq4pHe|uvemr!v*NE{k*^?jr5mv7dCJ0I(eh348!mgIZtLXbG|3eZKfq{@>~DNk<-Z3R#H1mq}EZ(Tr`Rb z*&f(^npGoso4_@s_SKSZLO8pgNM=r2Z{UUXh7Iqqi7#elY1S*Ic~TNHN^0tH9W2&F z`s%ZG8fvyBl?v!{N^@eoRiyU=XYaGk%BT;C+?M$GL&3hlGD zk-*tl8I2KMY=p&ut*9f7v(~t7iO_FFsWZ=b`<+zpey3B(TK@EasWMQrT)m1ms#;b4 zuHG|RYeg)SeSI;;^SVvF!(}IpVlsN>_qIfCa>;aR?l)PD%7tF*+Nxfz{97+9$gVG4 z-B+&qMzmt@?;Yg%#ZiE_G|$rhm|8^7INYzO{?sh`Q0|6i!phM7JryFT^?h9hn9G}c z5_)qH<0&}tO66%VD^&|y(nq@qJ9=1zXX9?vj9VJkzBoql1bhloK?8g!Y=%=LtlNoZ z+jyucQuO zsM#<}ypR*0%H)bziiyR%`@LozhHB;)EFQGTM=oM{T@tXX!IOluB5Lw#8f!zY zGZKW*nAHJ2tMAx(9_GG{KgSmMA6AjOX+2%cigop5e@K;#dFkPFr%TCgx)!Zc zXcwv0Qx(osX)#r*#JETW=6!Gb@jsAHzeQ=$_X6f-`5Bq_jG)u8Z?U6SaR!&Q9D~T~ z{7Ap4gsp#I25;*96TbK~d^6Fl8^FsHUvX{(CZ6Lw78XjakDDfrvroW0-^R@}Gr{&9 zctd{fyLM7+?Wgy#G8Ny`ON(VO<&G1=5%gC{|5J%=#lm8EsBxy64Hd}A+_!=L<(hYv z*&>d%C;T;qOE0-BpUN_tsN=Y3$8yAgJL1@drHhGR{xed3gxkv5sN#|%`2mA|Z#JCaSUCwvNups?^LCYvCG%^}>+U0GB@wo2? z(i%TbcMSb7^Ko{n zel<}yb>?~l9#BYmu*r{5#;cbksG9IITZRkwbA>SxmMOD9uZ%v^bNf>nIbEEzeOJgK zv0ilK6FRj7)gaW+oo;#NLaQcUFWnLmVH`VJfTaCCV&AscNK-Qcf7kD1M&Pv1z_5dBWUw{fUF#Dl7xwd6 ziYvrvS+c1vx+BAn9bK8h+aUU$j&Y^xPFNg}z0^0jOXiTN?lz_0bB~U_(Iai-uQg)} z$6cMe?&Bq+%Ewej%xu^X*foyqaTn3r%ZfUa0%~vFtf;9cer!7IKHnJM%`J~dJ@MRl zoVK;STgP>F0yXbx%Wq-3H;=vtj}t|frt_{nr^P8JEO1tLT(*u<9Z&85Jj8-*qXsof9n& zseytmA7R*B?KrI_Wq_8!r8qA49{uQ2GTTm(Z;N?la9Q1U%cG=r0=YP$OfJcAb|Y{* z{Le<1eBc9L9Y3wR7dEy1oG9wEn4+c{7}UoJ{TIEStz*%ds%kWUufJEWDoC!OOWDg@ za^uF))3RQJ#CD3^(eUW1zVeJI9JZaA{((iSD)_NhJdEE`+y%q3^qD6-vIVX7hQcjj zh=~_z;-wzm^k~2LzMnbnKO5_(`-dvNr-u;$%qFtr>SW4vp-kxQw@7(6;a3nrc5~u_4F^N106Swk_n8a$6?G_RFv=ycIZXemEHfUS{}548fbX zgtxoKi+-fU3H8(p$HlEOJsi>vC(W@a{VprtxDqvA$=ganq*l(mHgPf=!xp2b1vPY4 z9p0HTLklXq$Y_+X9avJj$YrX?uq*s{t6m;W-CKSYDZ2|7Bd6CWhli2$yW%P)Nm-b; z3zv#m$Vo-HR$Zot+drU7A>#7Aa@K4T*c*TL0tc-KFN@XG^(jeotdohNPh@6OQ>2~~kyPN~bTsQjP541g z_XV%x3@($yB%P9BF7n4U$$__4BKuY*Zg#j}@6yGK8SmN5W7`#CBI4E*`e!jL&w*QK z(V0R_N=e3e@y7W0g84rDl)Qt*(pc}6-Zq8NyVX-BkXbtQ5)%zB1!KbJ+*;SZ-#2_g z@?zyV`+A=o2NY+3@MfQNtMof5-i$|y&4MeQ;OV+T|N2j46L?s6MgHl-I89@|ZgR{t z7LiZDIxa$Z^8ua~foo(n^VMv6(!33HIh;3)uD!A19<917mw?SH2<0E~l2XE%3F~mz;!_1;9Hr4jf3@t)dL`w{9-la}|op%d$ zd{GXHi7wxFg+C^C-@ozsd915^+!%Nq@XUIsEaihu0d zs9&~z|2#Z5olmE#(t6_gaDhk93SU)s15lL^x>7+;V9knP%YLJpUlnf}Crmo)8&o4R zSz3~azhJ^aK!k$}Nv8j&Y2mc8=6rCO_i#oPb8Ol&-h2(AUMN2{%%Ynae4G}+&$g$a za#70Um8M%we^EYxO2*v@TAoW(LGV_y+;49c1=+rT{!+B+&P(doUF|bG$Yk9tRAm5( zk~Wv89@{)S6UPiR-$8387P|G7CN^Z2hk0~#>xOD(dRyR0WtjDJ^+TngDPy?Y)Z^7*ii-$xYYdk=v4&OV%+ix z-nIR<-MA`>sw+WkU{$u>RHXajJO2nE_Ry4;Wz@eDqPH#e4sQAoKtF zP3X*ksm#UGhQ|Ik$ix+Anf~PeC?j{?5I3OdI^JRM>XG_R-COp*1kW_K{jUuFT{r&kn9Y_PiCuBBgN*a?g}Tb&pnUC`qP3{Rt|)+-ra6Nz{$=w zLS1S%PIm-=2j;Sp_toowv4Fq2!6tClxv~Gy0H0go@pHR&wo&V*JEV^AOeY(-dqg;4 zfOj^g50JXG%c%d8t^Z}^f29KUy#7CCD-?cxyi3H5+cHp( zUug@`VIjf?2HKru~vijhDxJds?d zzbxg1dC_U#UTA+ZH(^PDzZrDe;|l>F=u>{oy{lU3CO%KpiXxbUktAomxe7Z?izxxf z`Mv386XlHMRiAHn!fP&ep3vP@zIOlQlowV2i)i&LvKvoz44u6jM~|HHM*KPj|38296!;q4uHnEg@8u;J}_&Qk__Ns@E^V&Ij9 z{|Kh{VMHNmtsU6X75Jf zCM|&9*L8hVyLeVZ@3>tt5=UVmj~?GJrpZsB0b63Yw+!N4u+GeN4x|B2R1G(238Ycb z_0j2X8q{G|XE2kG|4;ws+?@>C9XaXsU3~9E@5J$L=Z<^PgXic}u$5dHz`lfvifZP@ zW5Z}2&OOGuI{>Ov2UI8fS#^5U44PNp{C0ynYV@{Tb%M=q3 zJOuE89cz7v%+D?SsWU-c`~Tt30d*$X`RtK^lUf$EZbh&H{Q)L@eLZxnZgd9HGk~G(uc7Kp1Jg7}`zL%w zS6m!cp_!xJdf%fXrB!BD1uL$wk3Q19dlc84_lK_mHCav8uK_<&t;O@ysn6<$7km`oTUtrzEN`1*-p(PN8q z9|R$ZLzU=TVQa+XBz=RFmvCDMiGcj;;OhnuchLq8yQ0(zXhkcOV%YwPZ5i=1mW$M; zhI@}MX$kS&EVDf@Z)v!En=TKjOh?7@@1T9oX`)nz-#+PW7Y=fVIMNCTzQvh%P}K31 zTvI3&XD}XG$%Se6?8ovx2yXg;^V9xjrw*L8;vM$rAcOlwbqyoW8K$oF#g5Cdk57x> zOxzfNe#}xd>!Q;tZqjWw(VOHQA?gBo#QHhtE7HC#!b-6jI!HCy0=%s@rCxBnR#I>N zMgQJOJ@$k`Tao-+m^&5GAQ8-o>U!sHDw)&ho zT798gtUhXT)es&xGu@P{pF^22Fc+S#D zyQGxHMT5vpo%!iEmNIzs*A-#AC*~?<$Xt|JKD7?*K&Y)oQ+IJw*{9LPd>;JDFyJ34 zuNl&l_N?`{kY>)nq?6bPdZeW2VlTGT#fuc&>e*O}n#n>rHI>)56sJSnQJr(|m;l3` z1vC|c^g3`30a~7y*1mCBx#)*p+RB_Jt<{9>n4_+cM(q5`Cb_83BwbsgicTF>0k9iA zpA%=H5h-C+EBwHcu%U(1U0a~2>@Gjh*q?xpf0^f(AJofdE>a{3w`caJg);AKg)gk@ z88EB%*K^B%ZmH)y|K64<*ec1YDl%&oO;=wCZ4=i61CIztLP_M(e7Wh$-iA&#F(Rh! zj`;@v?3xP9%^T;ZNsqzB!uidcRhElu@~qt$dmNs~@8ytGYsfK}dKM@OcbW9}5A$As zYc@_VoU@p99d=nW&9*^m#I?na)hnNE>pV!cc_h>V(jxN9*;e~xH8O{dKg!WqPb~5m z$2Qn%QQFPKW)|z&ag>~ta#Xp_Odnd!XUT=ti*0B=`5_>tt7SNU&S4lJ@+SGslV-+- zs4HXo)@dksE&KwQd%{ zP*Tv-P^SWwU)ds4{wP4=<2QobA{gILf8jLMRlW*ceqxt?%z`d_VCQ11OXes3gvPX! zZdI%4@YlpUEz1gJn~$B1HG{nHY^xduR++1*Opbhc-{^2D(z^&BL78(M^eoWJ@GRo8 zwL_0KM{xp4Il^^T*xZKnVdlyWwafL=-LfG(c0^wHeumgRrPjp?;TJ^=6+(2qN|MEP zi8updZlP}vV(d!{;k})R{?`lzNxngf#0ed4?3IB4noU?sFRgWh1Tx5Q#J}Cwd1Q_; za|eD#ojNaXsktGN`Me)H+S!cbwt7Q3lf}2>+!u6&1yz^0wH6 z(z2%Z8IRYZyV-b%h>D1oUVfA_K1)TUSpoYce z!f`{(JzK!CrVXsxVvzRNL}k{x(l{)S`g={{=0q!l_vs+otPBg1QK6kp*_f;bLjP!k zUS)b}bTnh8k|e$K=ob-jmlTHjp+a4Mjlz|R#N9V`+v%4Ru`H|>n zXGHyHVOV+ofUy52Cos^o?cKDtsAcP75&o@jm}g5Ioww?+*BCgJ!9cT54F;_Y-`(Pn zil07gWTTd}+r|Cq^`d@W2h%3yYv(dxIeqPdMQycWg`MQI`Pi0^cDbl_&z5Q5XCVUR zSV+8$GgjS~)5Y{=0sp%pilWv3POb>f2~koP2!Tnt(+2`WTls zSoXOejPPLD`&cTp82?^F5B5LUO$7`+0g5tQGy79E5+S!YM(Ii&Y|6E5vQw+qwJH_! zsgQ)DRFLYYbmf#+e@@xlDI3slHU2W0lT1p1N_a4*&Hdv;!A+i4l2!2ffxWMeYQn=G z7+{0@F8sjjk)cps{tOyRfvG?MRZoPN^6v>FiJ65~c%~+LeKTBh)e-0t>8Nk=Gv5OA zLvGTdHhwc#BM)$AMKH;2^nB^#{w6j2VMuFLe5rA8fZW=UNGM`((j%!T%DRCIEz!Vm z?=4))_W``J2hbmqd9Asjq4`O}&f@}w0$YLyx!-6iM?UH}GBYAesNS$DDs^wI+=|76 zVZ?j?oDm)(b2sT*Zk~fX_CKq`zRfCypIUA$6LnawWw&Lz*;FF4(})K5aNn2C}l;H(RmSu6FwUH2IVc11$Su!;U5D?UF7}7y5$| z8<+i&wkp%u?=lI{){HH{#$}@T(|)%dBHL^(qDq#bkA&{S8QY;aU zJ@G3nC#m)bD?ByZ;w@e5;>cd-MoQUuC$x3$f3$DP3S2$c)CtDrrln?59Ed*IuPm-c z1`s@XQ1BnI*~_K;xiBSL?YAL~wL?WyH6Waa3o(a}u$5{Yo0?zUY$f_VxEJ7H&Vg9^m`fRR*)756ZkBoO`^B2*S~i39akF+(-olz-`=rxe6$Mh5QPU&GG(6V|$*)+-ty*Qgc6R)*|%94G0z@p%o4r{&hfJgWQy>xUDcATpgx1BP?{#z=_xD#n_ z^(|w#woJ`~5|CT&AB(R7Yj4-EokdTS$g2+|#qoY;uPG#mSx1+yn3>4R(ZmtjZb>kk zaPP9>*xV}~AKzFSAO3nAB&6^QCYV)llkI~ehwos(XRMFUHNHgmVCG|g^G4<;1R@;6 zgfCU%Vr`A%jhGEZH1?$U^Ix6<=DJVt5a3?&njOsN9jpW8SO4eA=q_Ls&XfAByCl{xK8t?mP3nffQbqaBlT2?L{yC$Z?=m47LF z6WXU|Kh5W@e$$ULkrr9UCry(WqZybr+BuwO$JEc8Hr!BJIq#DQ&0`hBMq}6?uL5kAHqN`eX1KR_c&YR4V>$ z*(altMIJTwHC24v6f(vE>a;$DEBKaM*YmbEXeXrrL2kAb0*HH%FbB*R(+!}HyBMlT ze&q!z9dqYC?Cyp!JIKo~m_f9?q_?*!3x~D41xs0MvU}~{&2@jf{D~{S^%~Q2DZsa6 zc^?lUq8^NP5dbg;OY?1bmayY{lsA8yH;+EHc~6e*bvKeKMSenrr&3DG^ZB-KCo@oi z)s*l4W2DlwFg2KxoA{9_i8l6xKh;EWad3=*EpT#D_N8m>G45XWpx)lE#H?$U5K>(c zfh@7qg`*EOflf(^^uoG`U6}pl>TjK7+*H(MfK9A~C?}S^G{Y$&7iKM5KXDQSESO1X z^|x(zP=l|&mx#c$R?UyifL(g8rG;gKK>0Dx{9~FdfbIbP^>z^IF2E|rmx2#*hv^=y z9PI$;kKZgBN72XU|D722!~^FKxQw0}dU%L~d;sSW?kTjKHJX|lvn_$hMND1;eH03=HNkmo?1#13r~;y44c|2hSBveUu#mA9#aUiE*HHZhVSEBw!K-V zJmO17!7e|lo7?syY6texciP9Oz2k+2v0{lgoW>4Ab+FZV(p3$1xiLauJ=aR@eiun* zlhv+`v)5M)Exi)Ei(2^F5-`%B>g&k?D34XstY+(FAF}*PYPQw^)XqvF>#^G5x;;<& zqgMFr!grw`h36+Q8*6)On1i)M{QWt-pqeuu*gSo^bx8|t1cc*DEARCikv5{yPM7Fc z##5#bZ5{l4KMXN+v{T2)$yN z!&PfQHBXI_`C%ff^!!eL2?6UX9&$j#r#oJlC$;(pz_&2g^@6i zIjuOB&8Zu3%$5@CRj}l;%$+<@7<}_2NfBr7Xs7d|fFLLNBwofLH}b-G z_pTT&6((g3m65h?)o(p#s?oM|?1prs3ac;VhJ|XC!MnJR*_t<3IyM+i_7CP#K&BHz z8)dym#C{ujo!cNs{i0m9E?J`Ho=v2WbvAPCg(7D8#TL<81L>jQs^?ysvrl3|PEOwS z#e6GY>epJK=#68wlj;LIs^5#M5cWiAo*c(+cwuN2&ctrCkFE#9@@t>`&@~xfYOg8o z--DsZ{Ei7S2aoE-23+%2>aPI<4&S9z%r~XsMv_@_$v$tc1n+%3Dev)X6rZn3oGboq z$4=IOD}J@EL$(Wh6P96Q8p7k5pMH%dZ}r~VDY z9gsnkLv-PQNJnNN2W`tvUM-J@&JV|5arYSOO$C>-+~@N2%2rp9Uw@0IL382 zh@^$aLob4*qZQE4xNd2stS$tyqq5Vl-@3N1u{v0IB6Er~PHjsFcVfT)PQF-Kk38Xr zjje>3CqVe|x^+kJV#~_fxiMbaNaVOUjUOhK)zy|21)fbQPS?@Zs^S3YoJbk6@1&{^~|_ovapK)7?i2-5av!2KzLX%ZG?!D8rm~^ z;WmNfipjI?p}E5^at3=QOAR$^{B$GIz*zPyZuW~KiPgdE`PScDRw)K>nyd|-Kl02L z+ln2Y9hvWR);6+Lmls)D6%44Kx@1Eu1B|h1sWl!W9+JU)ynbA?CkMxU3_50qS5W=8 zgh8wH)q&&5!lbutlF}m{)=3A2H=)Godz5?C9N1h4Lv2dZM;OM&V=wEI<2^7H%GLNS zRgX5~xe8xeh`K{Z}p)6O49M<9XTW3%8Ct>^faMP6hQd6XS{V zYaF#_Mlp;hC&NxdjO0H>(-yEYT!5Ji?EdCUevl1wl|B6z=!Bqiga6tqsJsqq6k$ab z!;nVz&kMI@&}1{1$aU_!fdkVrn*I$j5J#Xl|6 zp8jWR!`N^#;J`kLwTK9NVl>}*H+I|?=5Pna(1^)$s#EXcHaK0#asDY;pQfL%q}Pbe zmFyJQLEq8LTuQ^i!G(O{ZQu1%pZk|h(vJZK9v>_B-YKDxGhVLvfRWn2TwJU6(`hvo z4jeCkl_I{`6uJokK!;`JvrAeW(_2aAX$NmyFgLBo-#J97?@ z#GX*I_Q1YWT#80B;&BWchRf$}^6FHi)jeK*|H#B^Hi`4~e- z7VdB~h4Flue}`+yT6yJW)nhTh{U+9Wuyd8qr0+QOY-Lh%86Rr@`KwNkH?Ag25T~V? zbAGsBME<%R<8?Tu>*i|=9bS;-XtD)~WZ+sdoFS6%`N>$wxZYAHPrIUssHJK33eM%E z?W-$I{pV);k+=YFYoN`}uFezU*(SNGMyzt$!UNx7qg)@(C~99}XzQZ7+-?1+KgTyxBLn46DbF0%}aN%?pWyKq6&VG7QcV;q#t3 zIib_o1Nj|V(BWuO1o{ps`2HzQI zwZ;+iakah{|BkmTMc`b#Zp=9J@z@!aM#0blN5_WouiZSy+U%P^0j=HNWdDk`cL+Ed zz?rz-BS8)45bU)gl)SZGI<+g_+@#BlfzA3zgJ+jL9bcPT5i1lHm7VRe=v7$Ca=^om4Z;w z8C9`Hy<}o2aKup0P9-H*@uAj1JnP$e>HxIVo7MR_@48# znt@%Dy<7CL+p09JA>qQ^htQ^;zek8>@SSY%M%&Ei}!P0A~{izW`^)!A_--?HMyt@%sR*wRogw>>u z3YC6uKGEbOL^R;sc6QI1Vky6^EcAHzkNJ2pA|?&;4>aaS-ix{kywDwwwyqG}*8oV! z1@A^Tcw^?Tk~B1Z;9dw!p}5TOwu}uRrG_sI4^NLQBxlhMjKy`GJl&snni^sTPFL); zj-r2f;V=3;#9fJauJ15K8-}}eo^mrJ6 zyC68XyB#q(pG@JGt}3TiU%wx0+JIcE-`Ip8UVvc#pE=!u3^E%>y`NheQ()12odD`jR>7wk_6ueCM`22)IX_{TeHxIk0>m`-9 z!YYBKQq}Jn?KsMa*>_@=be5p!>0#Jk zcW)OltBI3iQcvh?=wp^nd8B{DHMS(-l)zc*S3}}O;D`M7Co}3KXdNH~$ zd5h(C5>$P{Gq&o9oj5~Zc$P98HZpq!D%fuG_}F&12*f!A$+og@Bn5k|+*tlDGms^l zGax-|jwuq^RiWo$Du&t_7w08v)$1kXm$bU`tTlgMlo@Xy_7UBqA2NiwgXnJp_bzY1 z3F3=t^@QXu4$rv{;dYuaG<2$#4_Zfgfkcnipxb>!sG4^unpPpSlJZWNPw=a8ackjO z)oPxDoN(67Hws4qd|Hu0C(==`4O)YsGZpX!8IxNq1cpMKR8$p)QWyr2Na`KO^~#bR z_-atsYAXF5?1@jyPI+d4`v)$8rYr`tz}ExSoBl2>rUJ#f@2~KmaDXCkAHw-W8am4; zH)=I!=!B2x3w@&@wED~)jWyh!ya*mWSiH7Q=GQn;D4bkg_}FbQTa|@pK~}u`ulbI!w}@R$+|Dg z<&V6gj)Y@s?KyM33T{+%9n=X20Q%r%KKU_4+X5wckU`PY(je{K+raBEYOTgXJzq(; z*>nNu;STiG^#S220UnVNm!U^~O0?Lv7!$+S!FS(%X_$}#xX~ImP3t59NR5LXDx+em zksa=M_arYX!MlAz2c5bgqBY#f3uny~P>Brf*m)oo$CAkZ`K}LB61}4(yQTNuiy^LK zG7G-Ffe@w>tJW4@-aVZR<)Kxxkm@Dv*MYsa?&O@hZ$v5cPnO5Ek;pWet z`eX8CKk8#tB=xznzzuCide@!Jm}J8zm!LbF`}Wo)HO4PBeV*sSQ}y)SO~hYK4R;(~ zRZiMC9NG)wQI3pJ{QgK%Tv$`U`Z|A)PW3wd)~pxjs+a$r2%nFkfIj?lw?_Xl5l`0c z%8rIQspHb7X2g-qHhgRNbzs)D0t+9fL@^EiQh#b+-6Q~QS|*$vjj^70=0k6E51In2 z>860Iyl_Y2mY&3WPE<#D&maomMRqYH6OSxa|Suv70kIRnbBM>FxU?ID{{sS(JDzR&MWW@k_m*DPncD4P73sM_}lQ*s7ZYZ+PsNHszJbQ4?V*623V z_D+8JlgC0Uyxqqa>iJWAJWys+CI{ab4L`i#?fbHConG5excH^MT_x_RzMzhZIX2d$Th~QSOS(;VS3(C}|`p)X;5afGz^y!ZDi`+g@mq^lc z6-p8%2MrX)mr{A5iS|EiL!=IN%rE^JewgmFNRedykG3PoX?s`3c#lH}jFgX-Rmv!QMIys4-#Iih+@aJM5;x0RV4 z?Se@~myMgCP4jdZI|g~XY#Rs}!OOq5ns~ZybY+dvy!QU+*9xcc8-)uxr*J*SG4d%R zW_0wv;CCEjfedXEQ)|$}`aoD$NeJhzc;UWN>vzKVdG88OT%1}bbVyF7$o;aPS4qV# zU0H>1$qbhL6)|xR{igY;lj~^ujE`kyenJE zYp5m411TRl>ZDnXJ7{@zhUtX|uDU{7w@Bbg3>2=Mp9XP0!L-C&pT)cMY|(EO#Hu7d zlP8|aN?4l*h ztw&>kcL7Ue-%DOplZ;k!YNpkI>82d8y0wAzLS_D3LCP)FIqoNO4M&~~V$Xz+q=k%5 zL&fAr$ZgtT);0(C>nTD_1KvB1M*ZJJi!LkiJh2?L>}+R9Dde?76f1%(scB6E=wG^6#{G&+o3RNI6aL=ZB%Vit9U$q>cwdm zCF z8j8E;vVY@77WdAMyQK*^G$?|kBVRAhYjt$+K>XzZ$Cju|$?VYn5<`zS6hM4R&wilf z5?^wgG-)b>OL&~Os6@kjvl&q^8QNex*yqi@VqY>evwM_w*}6VXW}6GpgQ}PVUpcl8QI?{q)AjHQy`N&d;o#z9m(uSj(uk!` z8GRn|bLYwqH?)^52m4aXBLctK?C#I>n>xjXDL|^<7?<};!#ivG;4ORaXy@*PyLdz{ zIp?mpLlwMLMs$w0+)LzF^fI%gGql$ZsmzZ>C9`e9_?edoBuMKQ)6Z@7BX4DbMe-&c z{S<-&F)QmH^a(Lysh&sPXAgEVt0DE7or`k*&EjgpBS zMFIcYk}kvfwibom&rCLmDq4J7P%z z*M$v;d*#~E&^KDnHSHB$|od=z}_6%JwGoZ!% z)ME;@TJx1jS~uJIQquoLS%K;B$F0Y&rY&g#-vlpmUbHNo4ic>U0XJV-L;eNv>~JPn z6lw8$e#}2YDJCNMX*+EDmsl%y_GW(7v&Lvo2d={U;Hw#P!kAxK+3UM|yhHk7^@Z5J zl-tTI!GD6rwbRx|>2b$*NUnqyeE!@){yvRYO3ASu3~!kD2(58Oa^xeKyGE)b-0S)5 zTL0qD?Fi7L_JI#r_xjE@XRxRB_CtxS;R~rqzP-9ntn*4i#MB)PJEB=OsFNedzc8~% z`n{La8bY17k~5VAIXj#82wb}>d6lNbhFXHSg;24I@x0mO^;(j9o-($_J~caMF>XCK zS-{!}ZJPBWt~4zbYt8;io%DG#&w0lt+dI3XFVg$DNRO_8HCz1Opm;QNqTER$TAAL> z{MLI`9qyV+658U#E43(lJ*7`OPHbS6w(}M66MQpZ8!eAJi1cmKaN;48T95&Y9)&W?gRFGLD2J5NvDmAc*L z?B4_-;A#R3U8WDf&N#4WUjKM+-_HqQwL7jK&7Hjb>eI)ouXRL=CZ65n^NiouJm`Mh z9rKm?7rc2PD5EvWMPOKV=I-h+Wf$~M5c18|B($|}lGU(3DzaqaXT% za(Wr&EP3=~*TZ+`qW6E&)O-0ln)~R+TRSY#l(jP4i99(;Wpj{gV9j&?yXDLuq&Fqk zekumW4^mLw05(d6?u#l;v{@BxxOM;JAFl8G4DYPh_kXeMpOEW(p4C6=&m>({imdBW zU-(21I8SC+9W`I%aak$vWu8ycH(95?rl<8J&H;WAk zo%>Dd+#Tn&>z*z8uq8|P-OE7xx~}Zk1tLoMKX^+v-n+clWo~rTi@oc7C&$)*^1g87 z>zjq?;#?8ek&@V2Bc7;>+ry5CDKgByz^o|xwl5$N0YCaXqm-EseqNACAZUA({Gv-C?725HU1!gr(|FUY9=_hh=~ysN+emo`MdLF9%T zS;C1|_C0n2_KUjGj7*LlOI{}ZEoS>K+x?un$0ubotaGvU`m#Ax`+k{CZ5Mxe@b=yd zVsG-7CJL{TyVmjT?@9gQg`u_Q_wyBWBL&Xn-O|jZiAz5)?vRUa@ckj+wp%D3 zvaeA)1R83mT+QQkjxc@n-aowT=lXBbFRSlQyZvj&oeuv!(?hNQe^C9~8X&uAZQg;t zScO@Iw;yt@1(uz^HzC!Q&))62_B~zWl!1ox`o|MfW5YA|@X8OU{_#fMJA1Euugmz7S-VQR zROr*k)T=lCDxdwLnHO}|^_7@MUToC0xtR=Ry>{#TIkKnJz3BMc$6VvNKZd1!^9}e& zqy^LDrIA;E&#qk>Ti9*%*;a1V!uY(2Q~#Q52%o;=>ek%NuWzsF%i13lKT~{lS*Ub* zt?An(daE~_-M1oW|KFVdQ&MBb@0GaM@Gynhq literal 0 HcmV?d00001 diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md deleted file mode 100644 index 1691c5a823161..0000000000000 --- a/rfcs/text/0012_background_sessions.md +++ /dev/null @@ -1,291 +0,0 @@ -- Start Date: (fill me in with today's date, YYYY-MM-DD) -- RFC PR: (leave this empty) -- Kibana Issue: (leave this empty) - -- Architecture diagram: https://app.lucidchart.com/documents/edit/cf35b512-616a-4734-bc72-43dde70dbd44/0_0 -- Mockups: https://www.figma.com/proto/FD2M7MUpLScJKOyYjfbmev/ES-%2F-Query-Management-v4?node-id=440%3A1&viewport=984%2C-99%2C0.09413627535104752&scaling=scale-down -- Old issue: https://github.com/elastic/kibana/issues/53335 -- Background search roadmap: https://github.com/elastic/kibana/issues/61738 -- POC: https://github.com/elastic/kibana/pull/64641 - -# Summary - -Background Sessions will enable Kibana applications and solutions to start a group of related search requests (such as -those coming from a single load of a dashboard or SIEM timeline), navigate away or close the browser, then retrieve the -results when they have completed. - -# Basic example - -At its core, background sessions are enabled via several new APIs: -- Start a session, associating multiple search requests with a single entity -- Save the session (and continue search requests in the background) -- Restore the background session - -```ts -const searchService = dataPluginStart.search; - -if (appState.sessionId) { - // If we are restoring a session, set the session ID in the search service - searchService.session.set(sessionId); -} else { - // Otherwise, start a new background session to associate our search requests - appState.sessionId = searchService.session.start(); -} - -// Search using the generated session ID. If this is a restored session and the search requests have already completed, -// this should return quickly. -const response$ = await searchService.search({ - params, - sessionId, - options, -}); - -// When the user decides to send to background and move on, create the saved object associated with this session. -// Make sure to store any app state needed to restore this view and the exact search requests from before. -searchService.session.save({ - appState, - restoreUrl, -}); -``` - -# Motivation - -Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use -cases where cost is more of a concern than speed (such as year-over-year reports, historical or audit data, batch -queries, etc.). When running slower searches on "cold" storage or frozen indices, users encounter timeouts after 30 -seconds by default. - -In 7.7, with the introduction of the `_async_search` API in Elasticsearch, we provided Kibana users a way to bypass the -timeout, but users still need to remain on-screen for the entire duration of the search requests. - -By default, when a user navigates away before search requests finish, we cancel them. This is a good default behavior, -since there currently isn't any way for the user to later return to the results. - -The primary motivation of this RFC is to enable users to do the following without needing to keep Kibana open, or while -moving onto other work inside Kibana: - -- Run long search requests (beyond 30 seconds) -- View their status (complete/incomplete) -- Cancel incomplete search requests -- Retrieve completed search request results - -# Detailed design - -Because a single view (such as a dashboard with multiple visualizations) can initiate multiple search requests, we need -a way to associate the search requests together in a single entity. We call this entity a `session`, and when a user -decides that they want to continue running the search requests while moving onto other work, we will create a saved -object corresponding with that specific `session`. - -We will expose a new `session` service inside of the `data` plugin `search` service. The service will expose APIs for -the following: - -- Starting a new session (generating a unique identifier for this specific grouping of search requests) -- Saving a session (creating the saved object using that ID) -- Getting a list of sessions for the current user (including status, any necessary application data, and a URL to -restore the view) -- Cancelling an incomplete session (deleting the saved object and cancelling any incomplete search requests) -- Restoring a session (allowing search requests to resume instead of restart) - -We will also modify the existing `search` API exposed by the `data` plugin `search` service to optionally accept an -additional parameter, the `sessionId`, which will allow search requests to *resume* instead of *restart*. When -"restoring" a session, it is crucial that search requests are sent with *identical* search request parameters as were -sent originally. (For example, relative date ranges should be converted to absolute before passing the request to the -`search` service.) - -Applications query data from Elasticsearch on behalf of the end user in a variety of ways: - -- Using `SearchSource` (our higher-level abstracted search API, used by Maps, Lens, and most visualizations, exposed by -the `data` plugin `search` service) -- Using `search` (our lower-level search API that accepts raw Elasticsearch query DSL, used by Vega and Timelion, -exposed by the `data` plugin `search` service) -- Exposing a route that bypasses our `search` services and queries Elasticsearch directly, then manipulates the data -before returning a response (as in the case of TSVB and most solutions) - -The proposed APIs provide the tools necessary to run long search requests, view their status, cancel incomplete search -requests, and retrieve results, regardless of the mechanism used to query Elasticsearch. - -## Background session service - -The primary service which will facilitate background sessions is the server-side `session` service. - -When a `search` request is handled, and it contains a `sessionId`, the service will query Elasticsearch to see if there -is already a saved object for that session. If there isn't, then we will forward the search request to Elasticsearch and -receive an ID specific to that search request. We store that ID in memory, keyed off of a hash of the request parameters -and the current username. - -We will then periodically query Elasticsearch to see if there is a saved object for that session (meaning the user has -elected to continue the requests in the background). If we find a saved object, then we will update it to contain the -search ID keyed off of the request hash, and remove it from memory. - -Then, in the future when the same `sessionId` is sent with identical request parameters, we will retrieve the saved -object. Instead of sending all of the request parameters to Elasticsearch (and restarting the search), we will look up -the search ID, and send that to Elasticsearch (resuming the search). If that specific search request has completed in -Elasticsearch, the results will be available immediately. - -By default, results are stored in Elasticsearch for 5 days. We may consider adding an advanced setting that will allow -overriding this default. - -The background session service will also use the task manager to periodically monitor the status of incomplete -background sessions. It will query the list of all incomplete sessions, and check the status of each search that is -executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of -`complete`. - -## Server APIs - -The following APIs are exposed by the server-side `data` plugin start `search` service: - -```ts -session.getAll() -``` - -Retrieves all of the background session saved objects for the current user. (We can filter it to the current user -because when the saved object is created, we store a hash of the current user's username inside the object.) - ---- - -```ts -session.get(sessionId) -``` - -Retrieves the saved object for this `sessionId` (if there is one), including the request/search ID hash, status -(complete/incomplete), application data, and restore URL. - ---- - -```ts -session.save(sessionId, restoreUrl, appData) -``` - -Creates the saved object for this background session. Used when a user chooses to "send to background." - ---- - -```ts -session.delete(sessionId) -``` - -Deletes the saved object for this background session, and cancels all incomplete search requests for this session. - ---- - -```ts -session.getSearchId(sessionId, searchRequest) -``` - -Used internally by the search service when a search request is handled to look up the search ID (if there is one) for -this `sessionId` and `searchRequest`. If bypassing the `search` service, this would need to be called manually when a -search request is handled. - ---- - -```ts -session.trackSearchId(sessionId, searchRequest, searchId) -``` - -Used internally by the search service when the first response from Elasticsearch is received. After this is called, the -search service will periodically monitor if a saved object is created for this `sessionId`, and will update it to -include this `searchRequest`/`searchId` association. If bypassing the `search` service, this would need to be called -manually when the first response from Elasticsearch is received. - -## Public APIs - -The following APIs are exposed by the public-side `data` plugin start `search` service: - -```ts -session.start() -``` - -Starts a new session and returns the `sessionId`, a unique ID for this session that will be sent in `search` requests. - ---- - -```ts -session.set(sessionId) -``` - -Sets the `sessionId` that is sent in `search` requests to the given ID. Used when restoring a background session so that -search requests may resume instead of restart. - ---- - -```ts -session.clear() -``` - -Clears the current `sessionId` so that future `search` requests do not contain a `sessionId`. Automatically called when -users navigate between applications in Kibana. - ---- - -```ts -session.getAll() -session.get(sessionId) -session.save(sessionId, restoreUrl, appData) -session.delete(sessionId) -``` - -These APIS make a request to the corresponding server-side API with the given parameters. - - -# Limitations - -In the first iteration, cases which require multiple search requests to be made serially will not be supported. The -following are examples of such scenarios: - -- When a visualization is configured with a terms agg with an "other" bucket -- When using blended layers or term joins in Maps - -Eventually, when expressions can be run on the server, we will facilitate these use cases by adding support for -background expressions in the background session service. - -# Drawbacks - -One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase -load on the Elasticsearch server. Whether or not this may or may not be significant is something that should be -investigated. - -Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results -will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the -background session saved object has not yet been updated with the search request ID.) In such cases, the search requests -will need to be restarted. There is also the consideration of the memory footprint of the Kibana server; however, since -we are only storing a hash of the request and search request ID, we do not anticipate the footprint to increase -significantly. We will collect telemetry data to measure this impact. - -The results of search requests that have been sent to the background will be stored in Elasticsearch for several days, -even if they will only be retrieved once. This will be mitigated by allowing the user manually delete a background -session object after it has been accessed. - -# Alternatives - -What other designs have been considered? What is the impact of not doing this? - -# Adoption strategy - -(See "Basic example" above.) - -Any application or solution that uses the `data` plugin `search` services will be able to facilitate background sessions -fairly simply. The public side will need to create/clear sessions when appropriate, and ensure the `sessionId` is sent -with all search requests. It will also need to ensure that any necessary application data, as well as a `restoreUrl` is -sent when creating the saved object. - -The server side will just need to ensure that the `sessionId` is sent to the `search` service. If bypassing the `search` -service, it will need to also call `trackSearchId` when the first response is received, and `getSearchId` when restoring -the view. - -# How we teach this - -What names and terminology work best for these concepts and why? How is this -idea best presented? As a continuation of existing Kibana patterns? - -Would the acceptance of this proposal mean the Kibana documentation must be -re-organized or altered? Does it change how Kibana is taught to new developers -at any level? - -How should this feature be taught to existing Kibana developers? - -# Unresolved questions - -Optional, but suggested for first drafts. What parts of the design are still -TBD? - -TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES \ No newline at end of file diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md new file mode 100644 index 0000000000000..9716af162153c --- /dev/null +++ b/rfcs/text/0013_background_sessions.md @@ -0,0 +1,467 @@ +- Start Date: (fill me in with today's date, YYYY-MM-DD) +- RFC PR: (leave this empty) +- Kibana Issue: (leave this empty) + +- Architecture diagram: https://app.lucidchart.com/documents/edit/cf35b512-616a-4734-bc72-43dde70dbd44/0_0 +- Mockups: https://www.figma.com/proto/FD2M7MUpLScJKOyYjfbmev/ES-%2F-Query-Management-v4?node-id=440%3A1&viewport=984%2C-99%2C0.09413627535104752&scaling=scale-down +- Old issue: https://github.com/elastic/kibana/issues/53335 +- Background search roadmap: https://github.com/elastic/kibana/issues/61738 +- POC: https://github.com/elastic/kibana/pull/64641 + +# Summary + +Background Sessions will enable Kibana applications and solutions to start a group of related search requests (such as those coming from a single load of a dashboard or SIEM timeline), navigate away or close the browser, then retrieve the results when they have completed. + +# Basic example + +At its core, background sessions are enabled via several new APIs, that: +- Start a session, associating multiple search requests with a single entity +- Store the session (and continue search requests in the background) +- Restore the background session + +```ts +const searchService = dataPluginStart.search; + +if (appState.sessionId) { + // If we are restoring a session, set the session ID in the search service + searchService.session.restore(sessionId); +} else { + // Otherwise, start a new background session to associate our search requests + appState.sessionId = searchService.session.start(); +} + +// Search, passing in the generated session ID. +// If this is a new session, the `search_interceptor` will associate and keep track of the async search ID with the session ID. +// If this is a restored session, the server will immediately return saved results. +// In the case where there is no saved result for a given request, or if the results have expired, `search` will throw an error with a meaningful error code. +const request = buildKibanaRequest(...); +request.id = searchService.session.get(); +const response$ = await searchService.search(request); + +// Calling `sendToBackground`, creates a saved object for this session, allowing the user to navigate away. +// The session object will be saved with all async search IDs that were executed so far. +// Any follow up searches executed with this sessionId will be saved into this object as well. +const sessionId = searchService.session.get(); +const backgroundSession = await searchService.sendToBackground(sessionId); +``` + +# Motivation + +Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use cases where users want to analyze large amount of "colder" data (such as year-over-year reports, historical or audit data, batch queries, etc.). + +For these cases, users run into two limitations: + 1. Kibana has a default timeout of 30s per search. This setting is controlled by the `elasticsearch.requestTimeout` setting. Originally intended to protect clusters from unintentional overload by a single query. + 2. Kibana cancels queries upon navigating away from an applicaiton, once again, as a mean of protecting clusters and reducing unnecessary load. + +In 7.7, with the introduction of the `_async_search` API in Elasticsearch, we provided Kibana users a way to bypass the timeout, but users still need to remain on-screen for the entire duration of the search requests. + +The primary motivation of this RFC is to enable users to do the following without needing to keep Kibana open, or while moving onto other work inside Kibana: + +- Run long search requests (beyond 30 seconds) +- View their status (complete/incomplete) +- Cancel incomplete search requests +- Retrieve completed search request results + +# Detailed design + +Because a single view (such as a dashboard with multiple visualizations) can initiate multiple search requests, we need a way to associate the search requests together in a single entity. + +We call this entity a `session`, and when a user decides that they want to continue running the search requests while moving onto other work, we will create a saved object corresponding with that specific `session`, persisting the *sessionId* along with a mapping of each *request's hash* to the *async ID* returned by Elasticsearch. + +## High Level Flow Charts + +### Client side search + +This diagram matches any case where `data.search` is called from the front end: + +![image](../images/background_sessions_client.png) + +### Server side search + +This case happens if the server is the one to invoke the `data.search` endpoint, for example with TSVB. + +![image](../images/background_sessions_server.png) + +## Data and Saved Objects + +### Background Session Status + +``` +export enum BackgroundSessionStatus { + Running, // The session has at least one running search ID associated with it. + Done, // All search IDs associated with this session have completed. + Error, // At least one search ID associated with this session had an error. + Expired, // The session has expired. Associated search ID data was cleared from ES. +} +``` + +### Saved Object Structure + +``` +interface BackgroundSessionAttributes extends SavedObjectAttributes { + sessionId: string; + status: BackgroundSessionStatus; + name: string; + creation: string; + expiration: string; + idMapping: { [key: string]: string }; + url: string; // TODO +} +``` + +## Frontend Services + +Most sessions will probably not be saved. Therefore, to avoid creating unnecessary saved objects, the browser will keep track of requests and their respective search IDs, until the user chooses to store the session. Once a session is stored, any additional searches will be immediately saved on the server side. + +### New Session Service + +We will expose a new frontend `session` service on the `data` plugin `search` service. + +The service will expose the following APIs: + +``` +interface ISessionService { + /** + * Returns the current session ID + */ + getId: () => string; + + /** + * Start a new session, by generating a new session ID. + */ + start: () => string; + + /** + * Restore a session. Any searches executed using this ID will attempt to reload saved data. + * A restored session may be expired, meaning that following search requests will fail. + * @param sessionId Session ID to restore.`. + */ + restore: (sessionId: string) => void; + + /** + * Close the current session and start a new one + */ + clear: () => void; + + /** + * Store a session. + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @param name A display name for the session. + * @param url TODO: is the URL provided here? How? + * @param searchIdMapping An optional mapping of hashed requests mapped to the corresponding searchId. + * @returns The stored `BackgroundSessionAttributes` object + * @throws Throws an error in OSS. + */ + store: (sessionId: string, name: string, url: string, searchIdMapping?: Record)) => Promise + + /** + * @returns Is the current session stored (i.e. is there a saved object correspondng with this sessionId). + */ + isStored: () => boolean; + + /** + * @returns Is the current session restored (i.e. was loaded by calling `sessionService.restore()`). + */ + isRestore: () => boolean; + + /** + * Mark a session as and all associated searchIds as expired. + * Cancels active requests, if there are any. + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @returns success status + * @throws Throws an error in OSS. + */ + expire: (sessionId: string) => Promise + + /** + * Extend a session and all associated searchIds. + * @param sessionId Session ID to extend. Probably retrieved from `sessionService.get()`. + * @param extendBy Time to extend by, can be a relative or absolute string. + * @returns success status + * @throws Throws an error in OSS. + */ + extend: (sessionId: string, extendBy: string)=> Promise + + /** + * @param TODO: input arguments + * @returns a filtered list of BackgroundSessionAttributes objects. + * @throws Throws an error in OSS. + */ + list: () => BackgroundSessionAttributes[] +} +``` + +### Search Service Changes + +Since all search requests go through the `search_interceptor`, it will take on the responsibility for tracking the mapping between the request's hash and the async ID returned from Elasticsearch, as well as enriching the requests with any options required to restore an existing session. + +We're proposing the following changes to the `SearchInterceptor` API, and exposing them on the `search` service: + +``` +interface ISearchInterceptor { + /** + * Execute a search request. Uses synchronous execution in OSS and asynchronous execution in x-pack. + * If a new sessionId is provided, the `search_interceptor` will internally track the sessionId, a hash of `request.body.params` and the `asyncId` returned from Elasticsearch on the first request. + * If an existing session id is provided for a restore, the interceptor will define an option on the request, telling the server to use saved results, rather than re-running the Elasticsearch request. + * @param request TODO define typing! The request contains an optional `id` parameter for the `sessionId`. + * @param options + * @returns + * @throws + */ + search: (request: ISearchRequest, options: TODO) => ISearchResponse + + /** + * Calls `data.search.session.store()` with the provided sessionId and any mapped `async IDs`. + * @param sessionId + * @param name + * @param url TODO? + * @returns the session saved object + * @throws Throws an error in OSS. + */ + sendToBackground: (sessionId: string, name: string, url: string) => Promise +} + +``` + +## Backend Services and Routes + +The server side's feature implementation builds on how Elasticsearch's `async_search` endpoint works. + +When making an intial new request to Elasticsearch, it returns a search ID that can be later used to retrieve the results. + +When the server receives a search request that has a sessionId and is marked as a `restore` request, the server will attempt finding the correct id within the saved object, and using it to retrieve the results previously saved. + +### New Session Service + +``` +interface ISessionService { + /** + * Adds a search ID to a Background Session, if it exists. + * Also extends the expiration of the search ID to match the session's expiration. + * @param request + * @param sessionId + * @param searchId + * @returns true if id was added, false if Background Session doesn't exist or if there was an error while updating. + */ + addSearchId: ( + request: KibanaRequest, + sessionId: string, + searchId: string, + ) => Promise + + /** + * Get a Background Session object. + * @param request + * @param sessionId + * @returns the Background Session object if exists, or undefined. + */ + get: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Get a searchId from a Background Session object. + * @param request + * @param sessionId + * @returns the searchID if exists on the Background Session, or undefined. + */ + getSearchId: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Store a session. + * @param request + * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. + * @param searchIdMap A mapping of hashed requests mapped to the corresponding searchId. + * @param url TODO: is the URL provided here? How? + * @returns The stored `BackgroundSessionAttributes` object + * @throws Throws an error in OSS. + */ + store: ( + request: KibanaRequest, + sessionId: string, + name: string, + url: string, + searchIdMapping?: Record + ) => Promise + + /** + * Mark a session as and all associated searchIds as expired. + * @param request + * @param sessionId + * @returns success status + * @throws Throws an error in OSS. + */ + expire: async ( + request: KibanaRequest, + sessionId: string + ) => Promise + + /** + * Extend a session and all associated searchIds. + * @param request + * @param sessionId + * @param extendBy Time to extend by, can be a relative or absolute string. + * @returns success status + * @throws Throws an error in OSS. + */ + extend: async ( + request: KibanaRequest, + sessionId: string, + extendBy: string, + ) => Promise + + /** + * Mark a session as and all associated searchIds as canceled. + * @param request + * @param sessionId + * @returns success status + * @throws Throws an error in OSS. + */ + list: async ( + request: KibanaRequest, + ) => Promise + + /** + * Update the status of a given session + * @param request + * @param sessionId + * @param status + * @returns success status + * @throws Throws an error in OSS. + */ + updateStatus: async ( + request: KibanaRequest, + sessionId: string, + status: BackgroundSessionStatus + ) => Promise +} + +``` + +### Search Service Changes + +There are cases where search requests are issued by the server (Like TSVB). +We can simplify this flow by intoducing a mechanism, similar to the frontend one, tracking the information in memory. + +However, due to the fact that we are running in a potenitally multi-server architecture, each server will have to poll for a saved object with a corresponding sessionId to store the ids into it. + +### Server Routes + +Each route exposes the corresponding method from the Session Service + +`POST /internal/session/store` + +`POST /internal/session/extend` + +`POST /internal/session/expire` + +`GET /internal/session/list` + +`/internal/session/extend` + +### Search Strategy Integration + +### Monitoring Service + +The `data` will register a task with the task manager, periodically monitoring the status of incomplete background sessions. + +It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. + +Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. + +## Miscellaneous + +#### Relative dates and restore URLs + +Restoring a sessionId depends on each request's `md5` hash matching exactly to the ones saved, requiring special attention to relative date ranges, as having these might yield ambiguous results. + +There are two potential scenarios: + - A relative date (for example `now-1d`) is being used in query DSL - In this case any future hash will match, but the returned data *won't match the displayed timeframe*. For example, a report might state that it shows data from yesterday, but actually show data from a week ago. + - A relative date is being translated by the application before being set to the query DSL - In this case a different date will be sent and the hash will never match, resulting in an error restoring the dashboard. + +Both scenarios require careful attention during the UI design and implementation. + +The former can be resolved by clearly displaying the creation time of the restored Background Session. We could also attempt translating relative dates to absolute one's, but this might be challenging as relative dates may appear deeply nested within the DSL. + +The latter case happens at the moment for the timepicker only: The relative date is being translated each time into an absolute one, before being sent to Elasticsearch. In order to avoid issues, we'll have to make sure that restore URLs are generated with an absolute date, to make sure they are restored correctly. + +#### Changing a restored session + +If you have restored a Background Session, making any type of change to it (time range, filters, etc.) will trigger new (potentially long) searches. There should be a clear indication in the UI that the data is no longer stored. A user then may choose to send it to background, resulting in a new Background Session being saved. + +#### Loading an errored \ expired \ canceled session + +When trying to restore a Background Session, if any of the requests hashes don't match the ones saved, or if any of the saved async search IDs are expired, a meaningful error code will be returned by the server. It is each application's responsibility to handle these errors appropriately. + +#### Extending Expiration + +Sessions are given an expiration date defined in an advanced setting (5 days by default). This expiration date is measured from the time the Background Session is saved, and it includes the time it takes to generate the results. + +A session's expiration date may be extended indefinitely. However, if a session was canceled or has already expired, it needs to be re-run. + +# Limitations + +In the first iteration, cases which require multiple search requests to be made serially will not be supported. The +following are examples of such scenarios: + +- When a visualization is configured with a terms agg with an "other" bucket +- When using blended layers or term joins in Maps + +Eventually, when expressions can be run on the server, we will facilitate these use cases by adding support for +background expressions in the background session service. + +# Drawbacks + +One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase +load on the Elasticsearch server. Whether or not this may or may not be significant is something that should be +investigated. + +Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results +will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the +background session saved object has not yet been updated with the search request ID.) In such cases, the search requests +will need to be restarted. There is also the consideration of the memory footprint of the Kibana server; however, since +we are only storing a hash of the request and search request ID, we do not anticipate the footprint to increase +significantly. We will collect telemetry data to measure this impact. + +The results of search requests that have been sent to the background will be stored in Elasticsearch for several days, +even if they will only be retrieved once. This will be mitigated by allowing the user manually delete a background +session object after it has been accessed. + +# Alternatives + +What other designs have been considered? What is the impact of not doing this? + +# Adoption strategy + +(See "Basic example" above.) + +Any application or solution that uses the `data` plugin `search` services will be able to facilitate background sessions +fairly simply. The public side will need to create/clear sessions when appropriate, and ensure the `sessionId` is sent +with all search requests. It will also need to ensure that any necessary application data, as well as a `restoreUrl` is +sent when creating the saved object. + +The server side will just need to ensure that the `sessionId` is sent to the `search` service. If bypassing the `search` +service, it will need to also call `trackSearchId` when the first response is received, and `getSearchId` when restoring +the view. + +# How we teach this + +What names and terminology work best for these concepts and why? How is this +idea best presented? As a continuation of existing Kibana patterns? + +Would the acceptance of this proposal mean the Kibana documentation must be +re-organized or altered? Does it change how Kibana is taught to new developers +at any level? + +How should this feature be taught to existing Kibana developers? + +# Unresolved questions + +Optional, but suggested for first drafts. What parts of the design are still +TBD? + +TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES \ No newline at end of file From 8f1b2a992394c27efdfaa686faf4ec3864834752 Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 17 Aug 2020 11:32:03 +0300 Subject: [PATCH 15/26] delete old version --- rfcs/text/0012_background_sessions.md | 146 -------------------------- 1 file changed, 146 deletions(-) delete mode 100644 rfcs/text/0012_background_sessions.md diff --git a/rfcs/text/0012_background_sessions.md b/rfcs/text/0012_background_sessions.md deleted file mode 100644 index 6e93792bd56ee..0000000000000 --- a/rfcs/text/0012_background_sessions.md +++ /dev/null @@ -1,146 +0,0 @@ -- Start Date: 2020-06-09 -- RFC PR: -- Kibana Issue: - -# Summary - -Kibana Background Sessions are a way to execute, track and restore a group of `search` requests, for a specific application configuration, like a single dashboard session or for a SIEM timeline tab. - -They can be used to execute long running tasks asynchronously, while the user is free to work on other tasks or close Kibana altogether. - -# Motivation - -Kibana is great at proving fast results from large data sets of "hot" data. However, when running slower searches in huge amounts of historical data, potentially on "cold" storage or frozen indices, users encounter a timeout that prevents them from running queries longer than 30 seconds (by default). - -While we already introduced an option to explicitly bypass this timeout in v7.7, users still have to wait on-screen for the results to return. - -The motivation of this RFC is to allow users to: - - Run queries longer than 30 seconds, while being able to work on other things (in the same application, different Kibana applications or closing Kibana altogether) - - Allow a user to restore a completed long running query, without having to wait. - -# Detailed design - -From the perspective of a user, when they run a view that takes a long time (A dashboard, a discover search, a SIEM timeline, etc.), they will recieve a notification stating that it can be sent to background, and returned to later. If they choose to do so, that view will be treated as a "Background Session": It will be stored and tracked for progress, allowing the user to come back and retrive the results in the future. - -## Session Management - -A session is a grouping of search requests, who's results are required to produce a specific view of Kibana. -It's an application's responsibility to manage its' sessions, by using the `data.search.session` APIs. - -### Starting a new session - -To start a session, an application should call `const sessionId = data.search.session.start();`, where `data` is the start contract of the data plugin. - -If the application uses the services provided by the `data.search` plugin, it only needs to pass down that `sessionId` to the search API, and the `search` service will track and restore requests internally. - - - If the request is issued using the `data.search.search`, use: - ``` - data.search.search({ - params, - sessionId, - } - ``` - - If the request is issued using `SearchSource`, use `searchSource.setSessionId(sessionId)`, before calling `fetch`. - -If the application doesn't use `data.search` services, you may still associate your requests with a `BackgroundSession`, by using the 'backgroundSession` service directly. Examples will be provided in the Detailed Design section. - -### Closing a session - -Each session is automatically closed when a new one is started. You may also call `data.search.session.clear()` to close a session without starting a new one. - -Sessions are also closed automatically when navigating between applications. - -If there is no open session, Kibana will act as before, suggesting a user to "Run Beyond Timeout" instead of "Run in Background". - -### Restoring a session - -Restoring a session means loading the results previously generated for each request within the session. - -If, for example, the `sessionId` to be - -Doing so requires a `sessionId` and *calling each request with the exact same parameters*. If the request parameters and the `sessionId` match, the stored results will be returned immediatelly, instead of re-running the search. - -If the `sessionId` is not found, the request parameters don't match or the stored results are expired, the requests will be re-run. - -### Embeddable integration - -TBD - -## Background Session Service - -The main component of this RFC is the background session service. - -It is a server side service, that tracks and stores sessions and all associated requests. -When a user starts executing a session, the service stores information in memory, until the user decides to "Send to Background" or until the expiration time. -If the use chooses to "Send to Background", all existing session info is saved into a Saved Object as well as subsequent requests with the same seesion ID. - -When a user wants to restore the session, the service can be user to retrieve the IDs. - -The service offers three public APIs: - -``` - // Track a searchId for a given session - // Automatically called by search_interceptor for each request - data_enhanced.search.session.trackId( - request: KibanaRequest, - sessionId: string, - requestParams: SessionKeys, - searchId: string - ) - - // Store session Id, while providing a URL to restore it. - data_enhanced.search.session.store( - request: KibanaRequest, - sessionId: string, - restoreUrl: string - ) - - // Get the searchId from a given session. - // Automatically called by search_interceptor for each request, if a known sessionId is provided. - const searchId = await data_enhanced.search.session.get(request: KibanaRequest, sessionId: string) -``` - -## Tracking Background Session Progress and Completion - -While the Background Session Service is responsible for storing a `BackgroundSession` in a `BackgroundSessionObject`, it does **not** track it's progress. Instead, tracking the progress is the responsibility of the monitoring flow. - -During setup, the `data_enhanced` plugin will register a task into the Kibana Task Mananger. The task will run in a configurable interval, fetching all Background Sessions with a `RUNNING` state, checking their state with ElasticSearch than updating the state to 'COMPLETE', 'ERROR' or 'EXPIRED' in case the data stored in ElasticSearch was expired. - -## Search Service - -Any request executed using `async_search_strategy`, with a sessionId specified, is automatically being tracked by the Background Search Service. -If that sessionId exists, it will be automatically restored from ElasticSearch, instead of being executed again. - -# Drawbacks - -- Background Session keys are stored in memory until a session is actually stored. - - This opens us to a possibility of data loss in case of server failure. (This data is not critical and will result in a user having to re-run a dashboard) - - Increased memory consumption on the server. (However, each object stored in memory is ~ bytes or ~ active sessions per 1MB and we'll have this tracked with telemetry). -- Users might send a request to run in the background, even if they only need to view the results one time. Results will be stored for a significant amount of time. - -There are tradeoffs to choosing any path. Attempt to identify them here. - -# Alternatives - -What other designs have been considered? What is the impact of not doing this? - -# Adoption strategy - -Any solution using the `data` plugin, can opt into using BackgroundSessions by starting to manage sessions (). -As long as there's an open session, all of the capabilities mentioned above will be enabled. - -# How we teach this - -What names and terminology work best for these concepts and why? How is this -idea best presented? As a continuation of existing Kibana patterns? - -Would the acceptance of this proposal mean the Kibana documentation must be -re-organized or altered? Does it change how Kibana is taught to new developers -at any level? - -How should this feature be taught to existing Kibana developers? - -# Unresolved questions - -Optional, but suggested for first drafts. What parts of the design are still -TBD? \ No newline at end of file From f607c499171018f179c8c675a6b72e942530e3be Mon Sep 17 00:00:00 2001 From: Liza K Date: Mon, 17 Aug 2020 11:53:05 +0300 Subject: [PATCH 16/26] somemore --- rfcs/text/0013_background_sessions.md | 31 ++++++++++++++++++++------- 1 file changed, 23 insertions(+), 8 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 9716af162153c..3c4827ff7c219 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -86,7 +86,7 @@ This case happens if the server is the one to invoke the `data.search` endpoint, ### Background Session Status -``` +```ts export enum BackgroundSessionStatus { Running, // The session has at least one running search ID associated with it. Done, // All search IDs associated with this session have completed. @@ -97,7 +97,7 @@ export enum BackgroundSessionStatus { ### Saved Object Structure -``` +```ts interface BackgroundSessionAttributes extends SavedObjectAttributes { sessionId: string; status: BackgroundSessionStatus; @@ -119,7 +119,7 @@ We will expose a new frontend `session` service on the `data` plugin `search` se The service will expose the following APIs: -``` +```ts interface ISessionService { /** * Returns the current session ID @@ -197,7 +197,7 @@ Since all search requests go through the `search_interceptor`, it will take on t We're proposing the following changes to the `SearchInterceptor` API, and exposing them on the `search` service: -``` +```ts interface ISearchInterceptor { /** * Execute a search request. Uses synchronous execution in OSS and asynchronous execution in x-pack. @@ -233,7 +233,7 @@ When the server receives a search request that has a sessionId and is marked as ### New Session Service -``` +```ts interface ISessionService { /** * Adds a search ID to a Background Session, if it exists. @@ -349,6 +349,19 @@ We can simplify this flow by intoducing a mechanism, similar to the frontend one However, due to the fact that we are running in a potenitally multi-server architecture, each server will have to poll for a saved object with a corresponding sessionId to store the ids into it. +```ts +interface SearchService { + /** + * The search API will accept the option `trackId`, which will track the search ID, if available, on the server, until a corresponding saved object is created. + **/ + search: async ( + context: RequestHandlerContext, + request: IEnhancedEsSearchRequest, + options?: ISearchOptions + ) => ISearchResponse +} +``` + ### Server Routes Each route exposes the corresponding method from the Session Service @@ -361,13 +374,15 @@ Each route exposes the corresponding method from the Session Service `GET /internal/session/list` -`/internal/session/extend` - ### Search Strategy Integration +If the `EnhancedEsSearchStrategy` receives a `restore` option, it will attempt reloading data using the Background Session saved object matching the provided `sessionId`. If there are any errors during that process, the strategy will return an error response and *not attempt to re-run the request. + +The strategy will track the asyncId on the server side, if `trackId` option is provided. + ### Monitoring Service -The `data` will register a task with the task manager, periodically monitoring the status of incomplete background sessions. +The `data` plugin will register a task with the task manager, periodically monitoring the status of incomplete background sessions. It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. From 38c3facc1abe8574eecf915f39d1acb8ea755dd8 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Mon, 24 Aug 2020 12:31:29 -0700 Subject: [PATCH 17/26] Update rfcs/text/0013_background_sessions.md --- rfcs/text/0013_background_sessions.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 3c4827ff7c219..631fed8003511 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -35,7 +35,7 @@ if (appState.sessionId) { // If this is a restored session, the server will immediately return saved results. // In the case where there is no saved result for a given request, or if the results have expired, `search` will throw an error with a meaningful error code. const request = buildKibanaRequest(...); -request.id = searchService.session.get(); +request.sessionId = searchService.session.get(); const response$ = await searchService.search(request); // Calling `sendToBackground`, creates a saved object for this session, allowing the user to navigate away. @@ -479,4 +479,4 @@ How should this feature be taught to existing Kibana developers? Optional, but suggested for first drafts. What parts of the design are still TBD? -TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES \ No newline at end of file +TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES From b3bb93b207f02e448d840c07746884a1895d6369 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Tue, 25 Aug 2020 16:22:37 -0700 Subject: [PATCH 18/26] Small updates --- rfcs/text/0013_background_sessions.md | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 631fed8003511..692cb5c5348f5 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -106,6 +106,7 @@ interface BackgroundSessionAttributes extends SavedObjectAttributes { expiration: string; idMapping: { [key: string]: string }; url: string; // TODO + metadata: { [key: string]: any } // TODO } ``` @@ -187,7 +188,7 @@ interface ISessionService { * @returns a filtered list of BackgroundSessionAttributes objects. * @throws Throws an error in OSS. */ - list: () => BackgroundSessionAttributes[] + list: (options: SavedObjectsFindOptions) => BackgroundSessionAttributes[] } ``` @@ -279,6 +280,7 @@ interface ISessionService { * @param url TODO: is the URL provided here? How? * @returns The stored `BackgroundSessionAttributes` object * @throws Throws an error in OSS. + * @internal (Consumers should use searchInterceptor.sendToBackground()) */ store: ( request: KibanaRequest, @@ -315,7 +317,7 @@ interface ISessionService { ) => Promise /** - * Mark a session as and all associated searchIds as canceled. + * Get a list of background session objects. * @param request * @param sessionId * @returns success status From bbfe10eb0e8cd07b6e7f480b1b7cf4265aee3970 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Mon, 31 Aug 2020 16:31:42 -0700 Subject: [PATCH 19/26] Update based on feedback --- rfcs/text/0013_background_sessions.md | 64 ++++++++++++++++----------- 1 file changed, 39 insertions(+), 25 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 692cb5c5348f5..d2c6c090d1e31 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -47,11 +47,11 @@ const backgroundSession = await searchService.sendToBackground(sessionId); # Motivation -Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use cases where users want to analyze large amount of "colder" data (such as year-over-year reports, historical or audit data, batch queries, etc.). +Kibana is great at providing fast results from large sets of "hot" data. However, there is an increasing number of use cases where users want to analyze large amounts of "colder" data (such as year-over-year reports, historical or audit data, batch queries, etc.). For these cases, users run into two limitations: - 1. Kibana has a default timeout of 30s per search. This setting is controlled by the `elasticsearch.requestTimeout` setting. Originally intended to protect clusters from unintentional overload by a single query. - 2. Kibana cancels queries upon navigating away from an applicaiton, once again, as a mean of protecting clusters and reducing unnecessary load. + 1. Kibana has a default timeout of 30s per search. This is controlled by the `elasticsearch.requestTimeout` setting (originally intended to protect clusters from unintentional overload by a single query). + 2. Kibana cancels queries upon navigating away from an application, once again, as means of protecting clusters and reducing unnecessary load. In 7.7, with the introduction of the `_async_search` API in Elasticsearch, we provided Kibana users a way to bypass the timeout, but users still need to remain on-screen for the entire duration of the search requests. @@ -97,19 +97,27 @@ export enum BackgroundSessionStatus { ### Saved Object Structure +The saved object created for a background session will be scoped to a single space, and will be a `hidden` saved object +(so that it doesn't show in the management listings). + ```ts interface BackgroundSessionAttributes extends SavedObjectAttributes { sessionId: string; + userId: string; // Something unique to the user who generated this session, like username/realm-name/realm-type status: BackgroundSessionStatus; name: string; - creation: string; - expiration: string; + creation: Date; + expiration: Date; idMapping: { [key: string]: string }; - url: string; // TODO - metadata: { [key: string]: any } // TODO + url: string; // TODO: A URL relative to the Kibana root to retrieve the results of a completed background session (and/or to return to an incomplete view) + metadata: { [key: string]: any } // TODO: Any data the specific application requires to restore a background session view } ``` +The URL that is provided will need to be generated by the specific application implementing background sessions. We +recommend using the URL generator to ensure that URLs are backwards-compatible since background sessions may exist as +long as a user continues to extend the expiration. + ## Frontend Services Most sessions will probably not be saved. Therefore, to avoid creating unnecessary saved objects, the browser will keep track of requests and their respective search IDs, until the user chooses to store the session. Once a session is stored, any additional searches will be immediately saved on the server side. @@ -156,7 +164,7 @@ interface ISessionService { store: (sessionId: string, name: string, url: string, searchIdMapping?: Record)) => Promise /** - * @returns Is the current session stored (i.e. is there a saved object correspondng with this sessionId). + * @returns Is the current session stored (i.e. is there a saved object corresponding with this sessionId). */ isStored: () => boolean; @@ -166,7 +174,7 @@ interface ISessionService { isRestore: () => boolean; /** - * Mark a session as and all associated searchIds as expired. + * Mark a session and and all associated searchIds as expired. * Cancels active requests, if there are any. * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. * @returns success status @@ -185,7 +193,7 @@ interface ISessionService { /** * @param TODO: input arguments - * @returns a filtered list of BackgroundSessionAttributes objects. + * @returns a filtered list of BackgroundSessionAttributes objects. * @throws Throws an error in OSS. */ list: (options: SavedObjectsFindOptions) => BackgroundSessionAttributes[] @@ -226,11 +234,17 @@ interface ISearchInterceptor { ## Backend Services and Routes -The server side's feature implementation builds on how Elasticsearch's `async_search` endpoint works. +The server side's feature implementation builds on how Elasticsearch's `async_search` endpoint works. When making an +initial new request to Elasticsearch, it returns a search ID that can be later used to retrieve the results. -When making an intial new request to Elasticsearch, it returns a search ID that can be later used to retrieve the results. +The server will then store that `request`, `sessionId`, and `searchId` in a mapping in memory, and periodically query +for a saved object corresponding with that session. If the saved object is found, it will update the saved object to +include this `request`/`searchId` combination, and remove it from memory. If, after a period of time (5 minutes?) the +saved object has not been found, we will stop polling for that `sessionId` and remove the `request`/`searchId` from +memory. -When the server receives a search request that has a sessionId and is marked as a `restore` request, the server will attempt finding the correct id within the saved object, and using it to retrieve the results previously saved. +When the server receives a search request that has a `sessionId` and is marked as a `restore` request, the server will +attempt to find the correct id within the saved object, and use it to retrieve the results previously saved. ### New Session Service @@ -243,6 +257,7 @@ interface ISessionService { * @param sessionId * @param searchId * @returns true if id was added, false if Background Session doesn't exist or if there was an error while updating. + * @throws an error if `searchId` already exists in the mapping for this `sessionId` */ addSearchId: ( request: KibanaRequest, @@ -347,9 +362,9 @@ interface ISessionService { ### Search Service Changes There are cases where search requests are issued by the server (Like TSVB). -We can simplify this flow by intoducing a mechanism, similar to the frontend one, tracking the information in memory. +We can simplify this flow by introducing a mechanism, similar to the frontend one, tracking the information in memory. -However, due to the fact that we are running in a potenitally multi-server architecture, each server will have to poll for a saved object with a corresponding sessionId to store the ids into it. +However, due to the fact that we are running in a potentially multi-server architecture, each server will have to poll for a saved object with a corresponding sessionId to store the ids into it. ```ts interface SearchService { @@ -386,7 +401,7 @@ The strategy will track the asyncId on the server side, if `trackId` option is p The `data` plugin will register a task with the task manager, periodically monitoring the status of incomplete background sessions. -It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. +It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. If the search requests have expired, it will update the saved object to an `expired` state. Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. @@ -394,7 +409,7 @@ Once there's a notification area in Kibana, we may use that mechanism to push co #### Relative dates and restore URLs -Restoring a sessionId depends on each request's `md5` hash matching exactly to the ones saved, requiring special attention to relative date ranges, as having these might yield ambiguous results. +Restoring a sessionId depends on each request's `sha-256` hash matching exactly to the ones saved, requiring special attention to relative date ranges, as having these might yield ambiguous results. There are two potential scenarios: - A relative date (for example `now-1d`) is being used in query DSL - In this case any future hash will match, but the returned data *won't match the displayed timeframe*. For example, a report might state that it shows data from yesterday, but actually show data from a week ago. @@ -434,15 +449,16 @@ background expressions in the background session service. # Drawbacks One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase -load on the Elasticsearch server. Whether or not this may or may not be significant is something that should be -investigated. +load on the Elasticsearch server. Whether or not this is significant is something that should be investigated. Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the -background session saved object has not yet been updated with the search request ID.) In such cases, the search requests -will need to be restarted. There is also the consideration of the memory footprint of the Kibana server; however, since -we are only storing a hash of the request and search request ID, we do not anticipate the footprint to increase -significantly. We will collect telemetry data to measure this impact. +background session saved object has not yet been updated with the search request ID.) In such cases, the user interface +will need to indicate errors for requests that were not stored in the saved object. + +There is also the consideration of the memory footprint of the Kibana server; however, since +we are only storing a hash of the request and search request ID, and are periodically cleaning it up (see Backend +Services and Routes), we do not anticipate the footprint to increase significantly. The results of search requests that have been sent to the background will be stored in Elasticsearch for several days, even if they will only be retrieved once. This will be mitigated by allowing the user manually delete a background @@ -480,5 +496,3 @@ How should this feature be taught to existing Kibana developers? Optional, but suggested for first drafts. What parts of the design are still TBD? - -TODO: Possibly add parameter for `isNew` so that we don't need to unnecessarily query ES From 547345ed10f12114b3b03993ee247bf2d103e6a3 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Sun, 13 Sep 2020 09:09:12 -0700 Subject: [PATCH 20/26] Feature controls & benchmarking --- rfcs/text/0013_background_sessions.md | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index d2c6c090d1e31..87df639b31500 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -405,6 +405,10 @@ It will query the list of all incomplete sessions, and check the status of each Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. +### Feature Controls + +Background sessions as a feature will be enabled/disabled per role/space by an admin. When set to "all", the feature will be available in its entirety, and when set to "read" or "none", the feature will be unavailable (i.e. search requests will only continue to run while a user waits on page, with no way to continue requests in the background). + ## Miscellaneous #### Relative dates and restore URLs @@ -449,7 +453,9 @@ background expressions in the background session service. # Drawbacks One drawback of this approach is that we will be regularly polling Elasticsearch for saved objects, which will increase -load on the Elasticsearch server. Whether or not this is significant is something that should be investigated. +load on the Elasticsearch server, in addition to the Kibana server (since all server-side processes share the same event +loop). We've opened https://github.com/elastic/kibana/issues/77293 to track this, and hopefully come up with benchmarks +so we feel comfortable moving forward with this approach. Two potential drawbacks stem from storing things in server memory. If a Kibana server is restarted, in-memory results will be lost. (This can be an issue if a search request has started, and the user has sent to background, but the From c4db3162ad2f24e91e8ac5a8be967046879480db Mon Sep 17 00:00:00 2001 From: Liza K Date: Wed, 23 Sep 2020 08:31:19 -0700 Subject: [PATCH 21/26] Rfc updates --- rfcs/text/0013_background_sessions.md | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 87df639b31500..f8c40c71fca5c 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -362,9 +362,7 @@ interface ISessionService { ### Search Service Changes There are cases where search requests are issued by the server (Like TSVB). -We can simplify this flow by introducing a mechanism, similar to the frontend one, tracking the information in memory. - -However, due to the fact that we are running in a potentially multi-server architecture, each server will have to poll for a saved object with a corresponding sessionId to store the ids into it. +We can simplify this flow by introducing a mechanism, similar to the frontend one, tracking the information in memory and polling for a saved object with a corresponding sessionId to store the ids into it. ```ts interface SearchService { @@ -401,7 +399,7 @@ The strategy will track the asyncId on the server side, if `trackId` option is p The `data` plugin will register a task with the task manager, periodically monitoring the status of incomplete background sessions. -It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. If the search requests have expired, it will update the saved object to an `expired` state. +It will query the list of all incomplete sessions, and check the status of each search that is executing. If the search requests are all complete, it will update the corresponding saved object to have a `status` of `complete`. If any of the searches return an error, it will update the saved object to an `error` state. If the search requests have expired, it will update the saved object to an `expired` state. Expired sessions will be purged once they are older than the time definedby the `EXPIRED_SESSION_TTL` advanced setting. Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. @@ -431,7 +429,9 @@ If you have restored a Background Session, making any type of change to it (time #### Loading an errored \ expired \ canceled session -When trying to restore a Background Session, if any of the requests hashes don't match the ones saved, or if any of the saved async search IDs are expired, a meaningful error code will be returned by the server. It is each application's responsibility to handle these errors appropriately. +When trying to restore a Background Session, if any of the requests hashes don't match the ones saved, or if any of the saved async search IDs are expired, a meaningful error code will be returned by the server **by those requests**. It is each application's responsibility to handle these errors appropriately. + +In such a scenario, the session will be partially restored. #### Extending Expiration @@ -447,8 +447,7 @@ following are examples of such scenarios: - When a visualization is configured with a terms agg with an "other" bucket - When using blended layers or term joins in Maps -Eventually, when expressions can be run on the server, we will facilitate these use cases by adding support for -background expressions in the background session service. +Eventually, when expressions can be run on the server, they will run in the context of a specific `sessionId`, hence enabling those edge cases too. # Drawbacks From 42d99658ce5583897c8a4a8d3d362d4ad7eb475c Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 24 Sep 2020 08:14:39 -0700 Subject: [PATCH 22/26] Clarify endpoints --- rfcs/text/0013_background_sessions.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index f8c40c71fca5c..f3169d3091638 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -379,7 +379,7 @@ interface SearchService { ### Server Routes -Each route exposes the corresponding method from the Session Service +Each route exposes the corresponding method from the Session Service (used only by the client-side service, not meant to be used directly by any consumers): `POST /internal/session/store` From dd296e5b97c8bd0e2b2f51ab0d2bc67cab5bb5e1 Mon Sep 17 00:00:00 2001 From: Liza K Date: Thu, 24 Sep 2020 08:59:38 -0700 Subject: [PATCH 23/26] Rfc updates --- rfcs/text/0013_background_sessions.md | 51 ++++++++------------------- 1 file changed, 15 insertions(+), 36 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index f3169d3091638..ab7f9fb8f0576 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -140,6 +140,18 @@ interface ISessionService { */ start: () => string; + /** + * Track a search ID of a sessionId, if it exists. + * @param request + * @param sessionId + * @param searchId + */ + trackSearchId: ( + request: KibanaRequest, + sessionId: string, + searchId: string, + ) => Promise + /** * Restore a session. Any searches executed using this ID will attempt to reload saved data. * A restored session may be expired, meaning that following search requests will fail. @@ -153,15 +165,14 @@ interface ISessionService { clear: () => void; /** - * Store a session. + * Store a session, alongside with any tracked searchIds. * @param sessionId Session ID to store. Probably retrieved from `sessionService.get()`. * @param name A display name for the session. * @param url TODO: is the URL provided here? How? - * @param searchIdMapping An optional mapping of hashed requests mapped to the corresponding searchId. * @returns The stored `BackgroundSessionAttributes` object * @throws Throws an error in OSS. */ - store: (sessionId: string, name: string, url: string, searchIdMapping?: Record)) => Promise + store: (sessionId: string, name: string, url: string) => Promise /** * @returns Is the current session stored (i.e. is there a saved object corresponding with this sessionId). @@ -200,38 +211,6 @@ interface ISessionService { } ``` -### Search Service Changes - -Since all search requests go through the `search_interceptor`, it will take on the responsibility for tracking the mapping between the request's hash and the async ID returned from Elasticsearch, as well as enriching the requests with any options required to restore an existing session. - -We're proposing the following changes to the `SearchInterceptor` API, and exposing them on the `search` service: - -```ts -interface ISearchInterceptor { - /** - * Execute a search request. Uses synchronous execution in OSS and asynchronous execution in x-pack. - * If a new sessionId is provided, the `search_interceptor` will internally track the sessionId, a hash of `request.body.params` and the `asyncId` returned from Elasticsearch on the first request. - * If an existing session id is provided for a restore, the interceptor will define an option on the request, telling the server to use saved results, rather than re-running the Elasticsearch request. - * @param request TODO define typing! The request contains an optional `id` parameter for the `sessionId`. - * @param options - * @returns - * @throws - */ - search: (request: ISearchRequest, options: TODO) => ISearchResponse - - /** - * Calls `data.search.session.store()` with the provided sessionId and any mapped `async IDs`. - * @param sessionId - * @param name - * @param url TODO? - * @returns the session saved object - * @throws Throws an error in OSS. - */ - sendToBackground: (sessionId: string, name: string, url: string) => Promise -} - -``` - ## Backend Services and Routes The server side's feature implementation builds on how Elasticsearch's `async_search` endpoint works. When making an @@ -259,7 +238,7 @@ interface ISessionService { * @returns true if id was added, false if Background Session doesn't exist or if there was an error while updating. * @throws an error if `searchId` already exists in the mapping for this `sessionId` */ - addSearchId: ( + trackSearchId: ( request: KibanaRequest, sessionId: string, searchId: string, From 21dae9aa55f12b277df32d93ae75b03e7e8f83ea Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Thu, 24 Sep 2020 10:50:44 -0700 Subject: [PATCH 24/26] More updates to APIs --- rfcs/text/0013_background_sessions.md | 77 +++++++++++++++------------ 1 file changed, 43 insertions(+), 34 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index ab7f9fb8f0576..7f506d76b8bdc 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -38,11 +38,10 @@ const request = buildKibanaRequest(...); request.sessionId = searchService.session.get(); const response$ = await searchService.search(request); -// Calling `sendToBackground`, creates a saved object for this session, allowing the user to navigate away. +// Calling `session.store()`, creates a saved object for this session, allowing the user to navigate away. // The session object will be saved with all async search IDs that were executed so far. // Any follow up searches executed with this sessionId will be saved into this object as well. -const sessionId = searchService.session.get(); -const backgroundSession = await searchService.sendToBackground(sessionId); +const backgroundSession = await searchService.session.store(); ``` # Motivation @@ -109,8 +108,8 @@ interface BackgroundSessionAttributes extends SavedObjectAttributes { creation: Date; expiration: Date; idMapping: { [key: string]: string }; - url: string; // TODO: A URL relative to the Kibana root to retrieve the results of a completed background session (and/or to return to an incomplete view) - metadata: { [key: string]: any } // TODO: Any data the specific application requires to restore a background session view + url: string; // A URL relative to the Kibana root to retrieve the results of a completed background session (and/or to return to an incomplete view) + metadata: { [key: string]: any } // Any data the specific application requires to restore a background session view } ``` @@ -133,36 +132,19 @@ interface ISessionService { /** * Returns the current session ID */ - getId: () => string; + getActiveSessionId: () => string; - /** - * Start a new session, by generating a new session ID. - */ - start: () => string; - - /** - * Track a search ID of a sessionId, if it exists. - * @param request - * @param sessionId - * @param searchId + /** + * Sets the current session + * @param sessionId: The ID of the session to set + * @param isRestored: Whether or not the session is being restored */ - trackSearchId: ( - request: KibanaRequest, - sessionId: string, - searchId: string, - ) => Promise + setActiveSessionId: (sessionId: string, isRestored: boolean) => void; /** - * Restore a session. Any searches executed using this ID will attempt to reload saved data. - * A restored session may be expired, meaning that following search requests will fail. - * @param sessionId Session ID to restore.`. + * Start a new session, by generating a new session ID (calls `setActiveSessionId` internally) */ - restore: (sessionId: string) => void; - - /** - * Close the current session and start a new one - */ - clear: () => void; + start: () => string; /** * Store a session, alongside with any tracked searchIds. @@ -180,9 +162,9 @@ interface ISessionService { isStored: () => boolean; /** - * @returns Is the current session restored (i.e. was loaded by calling `sessionService.restore()`). + * @returns Is the current session a restored session */ - isRestore: () => boolean; + isRestored: () => boolean; /** * Mark a session and and all associated searchIds as expired. @@ -203,11 +185,38 @@ interface ISessionService { extend: (sessionId: string, extendBy: string)=> Promise /** - * @param TODO: input arguments + * @param sessionId the ID of the session to retrieve the saved object. * @returns a filtered list of BackgroundSessionAttributes objects. * @throws Throws an error in OSS. */ - list: (options: SavedObjectsFindOptions) => BackgroundSessionAttributes[] + get: (sessionId: string) => Promise + + /** + * @param options The options to query for specific background session saved objects. + * @returns a filtered list of BackgroundSessionAttributes objects. + * @throws Throws an error in OSS. + */ + list: (options: SavedObjectsFindOptions) => Promise + + /** + * Clears out any session info as well as the current session. Called internally whenever the user navigates + * between applications. + * @internal + */ + clear: () => void; + + /** + * Track a search ID of a sessionId, if it exists. Called internally by the search service. + * @param sessionId + * @param request + * @param searchId + * @internal + */ + trackSearchId: ( + sessionId: string, + request: IKibanaSearchRequest, + searchId: string, + ) => Promise } ``` From eef7cfb62d1ffd798fdfed99656793524dcbc4ce Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 30 Sep 2020 11:38:21 -0700 Subject: [PATCH 25/26] Clarify saved object hidden --- rfcs/text/0013_background_sessions.md | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 7f506d76b8bdc..0ee3bd01f5b3b 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -97,7 +97,9 @@ export enum BackgroundSessionStatus { ### Saved Object Structure The saved object created for a background session will be scoped to a single space, and will be a `hidden` saved object -(so that it doesn't show in the management listings). +(so that it doesn't show in the management listings). We will provide a separate interface for users to manage their own +background sessions (which will use the `list`, `expire`, and `extend` methods described below, which will be restricted +per-user). ```ts interface BackgroundSessionAttributes extends SavedObjectAttributes { From b9666f8ba64e66c464d47f4526cf1d10084eda56 Mon Sep 17 00:00:00 2001 From: Lukas Olson Date: Wed, 30 Sep 2020 16:23:18 -0700 Subject: [PATCH 26/26] Remove undecided feature controls section --- rfcs/text/0013_background_sessions.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/rfcs/text/0013_background_sessions.md b/rfcs/text/0013_background_sessions.md index 0ee3bd01f5b3b..056149e770448 100644 --- a/rfcs/text/0013_background_sessions.md +++ b/rfcs/text/0013_background_sessions.md @@ -393,10 +393,6 @@ It will query the list of all incomplete sessions, and check the status of each Once there's a notification area in Kibana, we may use that mechanism to push completion \ error notifications to the client. -### Feature Controls - -Background sessions as a feature will be enabled/disabled per role/space by an admin. When set to "all", the feature will be available in its entirety, and when set to "read" or "none", the feature will be unavailable (i.e. search requests will only continue to run while a user waits on page, with no way to continue requests in the background). - ## Miscellaneous #### Relative dates and restore URLs