From ef66d02b26ac63307d583af2f30c13db1fc2c0ec Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Thu, 7 Nov 2024 17:44:45 +0000 Subject: [PATCH 1/5] first swing at collections docs --- adaptors/collections.md | 200 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) create mode 100644 adaptors/collections.md diff --git a/adaptors/collections.md b/adaptors/collections.md new file mode 100644 index 000000000000..bee3fb9a036d --- /dev/null +++ b/adaptors/collections.md @@ -0,0 +1,200 @@ +--- +title: Collections Adaptor +--- + +## Collections Overview + +The Collections API is a key/value storage solution. It is designed for high +performance over a large volume of data. + +Use-cases include: + +- Storing mapping objects for use in workflows +- Buffering and aggregating high volumes of incoming data +- Caching and sharing state between workflows + +A Collection is bound to a project. Collections can only be accessed with a +token associated with that project. When running on the app, a workflow is +automatically granted access to all collections on the same project. When +running in the CLI, a Personal Access Token can be used (generated from the app +at /profile/tokens). + +## The Collections Adaptor + +The Collections adaptor is a special adaptor. Uniquely, the Collections adaptor +is designed to be run _alongside_ other adaptors, and is injected for you by the +platform. + +This makes the Collections API available to every step in a workflow, regardless +of which adaptor it is using. + +## Usage Guide + +### Set some data in a collection + +The Collection API allows you to set a JSON object (or any primitive JS value) +under a given key: + +You can also pass an array of items for a batch-set. + +### Getting data from a collection + +To retrieving multiple items from a Collection, we recommend using the `each()` +function. + +`each()` will stream each value individually, greatly reducing the memory +overhead of downloading a large amount of data to the client. + +```js +each('my-collection', '2024*', (state, value, key) => { + console.log(value); + // No need to return state here +}); +``` + +The second argument to `each` is a query string or object. Pass a key with a +pattern, or an object including different query strings. Check the API reference +for a full listing. + +```js +each( + 'my-collection', + { key: '2024*', created_after: '20240601' }, + (state, value, key) => { + console.log(value); + } +); +``` + +You can limit the amount of data you want to download with the `limit` key. If +there are returned values on the server, a `cursor` key will be written to +`state.data`. + +```js +each('my-collection', { key: '2024*', limit: 1000 }, (state, value, key) => { + console.log(value); +}).then(state => { + state.nextCursor = state.data.cursor; + // state.data.cursor now contains the cursor position + return state; +}); +``` + +You can fetch items individually with `get()`, which will be written to +state.data + +```js +collections.get('my-collection', 'commcare-fhir-value-mappings').then(state => { + state.mappings = state.data; + return state; +}); +each($.inputs, state => { + const mappedString = state.mappings[state.data.diagnosis]; + state.resources ??= {}; + state.resources[state.data.id] = mappedString; + return state; +}); +``` + +You can also fetch multiple items with `get()`, which supports the same query +options as `each()`. + +Bear in mind that all the items will be loaded into memory at once. For large +datasets and structures, this may cause problems. + +When bulk-loading with `get()`, state.data will be an array of items, and +`state.data.cursor` will contain the cursor position from the server + +```js +collections.get('my-collection', '2024*').then(state => { + state.allRecords = state.data; + return state; +}); +``` + +### Remove data from a collection + +You can remove an individual item by key: + +```js +collections.remove('my-collection', 'commcare-fhir-value-mappings'); +``` + +You can also use the same query options as `get()` and `each()` to bulk delete: + +```js +collections.remove('my-collection', { createdBefore: '20240601' }); +``` + +## Collection Administration + +Collections must be created in the platform Admin page before they can be used. + +Collections can be removed from the Admin page. + +## CLI usage + +Collections are designed for close integration with the platform app, but can be +used from the CLI too. + +You will need to: + +- Set the job to use two adaptors +- Pass a Personal Access Token +- Set the Collections endpoint + +You can get a Personal Access Token from any v2 deployment. + +Remember that a Collection must be created from the Admin page before it can be +used! + +### For a single job + +You can pass multiple adaptors from the CLI: + +```bash +openfn job.js -a collections -a http -s state.json +``` + +You'll need to set configuration on the state.json: + +```json +{ + "configuration": { + "collections_endpoint": "http://localhost:4000/collections", + "collections_token": "...paste the token from the app..." + } +} +``` + +### For a workflow + +If you're using `workflow.json`, set the token and endpoint on +`workflow.credentials`: + +```json +{ + "workflow": { + "steps": [ ... ], + "credentials": { + "collections_endpoint": "http://localhost:4000/collections", + "collections_token": "...paste the token from the app..." + } + } +} +``` + +And make sure that any steps which use collections have multiple adaptors set: + +```json +{ + "workflow": { + "steps": [ + { + "expression": "...", + "adaptors": ["@openfn/language-http", "@openfn/language-collections"] + } + ] + } +} +``` From 4b846c8d0a2bef32a7a50e473d5bf904ab8d5ce3 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Fri, 8 Nov 2024 12:15:14 +0000 Subject: [PATCH 2/5] update set values --- adaptors/collections.md | 51 ++++++++++++++++++++++++++++++++++++++++- 1 file changed, 50 insertions(+), 1 deletion(-) diff --git a/adaptors/collections.md b/adaptors/collections.md index bee3fb9a036d..f571a91265ca 100644 --- a/adaptors/collections.md +++ b/adaptors/collections.md @@ -35,7 +35,56 @@ of which adaptor it is using. The Collection API allows you to set a JSON object (or any primitive JS value) under a given key: -You can also pass an array of items for a batch-set. +```js +collections.set('my-collection', 'commcare-fhir-value-mappings', { + current_smoker: { + system: 'http://snomed.info/sct', + code: '77176002', + display: 'Smoker', + }, + /* ... */ +}); +``` + +You can also pass an array of items for a batch-set. When setting multiple +values, you need to set a key generator function to calculate a key for each +item, like this: + +```js +collections.set('my-favourite-footballer', value => value.id, [ + { + id: 'player01', + name: 'Lamine Yamal', + /* other patient details */ + }, + { + id: 'player02', + name: 'Aitana Bonmati', + /* other patient details */ + }, + /* More patients {}, {} */ +]); +``` + +The key generator is a function which receives each of the values in the +supplied values array as an id (so, in the example above, it gets called with +the `player01` object, then the `player02` object, and so on). For each value, +it should return a string key, under which it will be saved in the collection. + +You can use Javascript template literals to easily generate key values which +include a mixture of static and dynamic values: + +```js +collections.set( + 'my-favourite-footballer', + value => `${value.createdDate}-${value.region}-${value.name}` + $.data +), +``` + +In this example, the `createdDate`, `region` and `name` properties will be read +from each value and assembled into a key-string, separated by dashes. This +technique creates keys that are easily sorted by date. ### Getting data from a collection From 2fff98326663a546a4b4fbb5676149e3756f0c4e Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Fri, 8 Nov 2024 12:39:10 +0000 Subject: [PATCH 3/5] better high level intro --- adaptors/collections.md | 55 ++++++++++++++++++++++++++++++++--------- 1 file changed, 44 insertions(+), 11 deletions(-) diff --git a/adaptors/collections.md b/adaptors/collections.md index f571a91265ca..a42ab30fe0aa 100644 --- a/adaptors/collections.md +++ b/adaptors/collections.md @@ -4,8 +4,8 @@ title: Collections Adaptor ## Collections Overview -The Collections API is a key/value storage solution. It is designed for high -performance over a large volume of data. +The Collections API provides access to a secure key/value store on the OpenFn +Platform. It is designed for high performance over a large volume of data. Use-cases include: @@ -13,23 +13,56 @@ Use-cases include: - Buffering and aggregating high volumes of incoming data - Caching and sharing state between workflows -A Collection is bound to a project. Collections can only be accessed with a -token associated with that project. When running on the app, a workflow is -automatically granted access to all collections on the same project. When -running in the CLI, a Personal Access Token can be used (generated from the app -at /profile/tokens). +Collections are secure, private datastores which are visible only to Workflows +within a particular OpenFn Project. They can be created, managed and destroyed +from the OpenFn Admin page. + +When running in the CLI, a Personal Access Token can be used to get access to +the collection (generated from the app at /profile/tokens). ## The Collections Adaptor -The Collections adaptor is a special adaptor. Uniquely, the Collections adaptor -is designed to be run _alongside_ other adaptors, and is injected for you by the -platform. +The Collections adaptor is a special kind of adaptor. + +Uniquely, it is designed to be run _alongside_ other adaptors, and is injected +for you by the platform. -This makes the Collections API available to every step in a workflow, regardless +This makes the Collections API available to every step in a Workflow, regardless of which adaptor it is using. ## Usage Guide +All values in a Collection are stored under a string key. Values are stored as +Strings, but the Collections API will automatically serialized and de-serialize +JSON objects to strings for you (so, in effect, you can treat keys as strings +and value as objects). + +Collections can be manipulated using a single key a pattern - where a pattern is +a string with a wildcard. So the key-pattern `mr-benn` will only match a single +value under the key `mr-benn`, but the pattern `2024*` will match all keys which +start with `2024` but have any other characters afterwards. The pattern +`2024*mr-benn*` will match keys starting with 2024, then having some values plus +the string `mr-benn`, plus any other sequence of characters (in other words, +fetch all keys which relate to Mr Benn in 2024). + +The Collections API gives you four functions to read, write and remove data from +a collection. + +- Use [`collections.get()`](adaptors/packages/collections-docs#collections_get) + to fetch a single value, or batch-download a range of values. +- Use + [`collections.each()`](adaptors/packages/collections-docs#collections_each) to + efficiently iterate over a range of items in a collection. Recommended for + large data sets. +- Use [`collections.set()`](adaptors/packages/collections-docs#collections_set) + to upload one or more values to a collection. `set()` is always an "upsert": + if a key already exists, it's value will be replaced by the new value +- Use + [`collections.remove()`](adaptors/packages/collections-docs#collections_remove) + to remove one or more values. + +Detailed usage examples are provided below. + ### Set some data in a collection The Collection API allows you to set a JSON object (or any primitive JS value) From e9cdee03bd278607ece36f99c6e0918c8703d4d5 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Fri, 8 Nov 2024 12:45:22 +0000 Subject: [PATCH 4/5] typo and notes --- adaptors/collections.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/adaptors/collections.md b/adaptors/collections.md index a42ab30fe0aa..ae4b4693e797 100644 --- a/adaptors/collections.md +++ b/adaptors/collections.md @@ -121,8 +121,8 @@ technique creates keys that are easily sorted by date. ### Getting data from a collection -To retrieving multiple items from a Collection, we recommend using the `each()` -function. +To retrieve multiple items from a Collection, we generally recommend using the +`each()` function. `each()` will stream each value individually, greatly reducing the memory overhead of downloading a large amount of data to the client. @@ -163,7 +163,7 @@ each('my-collection', { key: '2024*', limit: 1000 }, (state, value, key) => { ``` You can fetch items individually with `get()`, which will be written to -state.data +state.data: ```js collections.get('my-collection', 'commcare-fhir-value-mappings').then(state => { @@ -208,6 +208,14 @@ You can also use the same query options as `get()` and `each()` to bulk delete: collections.remove('my-collection', { createdBefore: '20240601' }); ``` +## Date Filters + +-TODO- + +## Limits & Cursors + +-TODO- + ## Collection Administration Collections must be created in the platform Admin page before they can be used. From e7c0e8d97ff274eb642b8cd03ecf4e7beef33ea5 Mon Sep 17 00:00:00 2001 From: Joe Clark Date: Mon, 11 Nov 2024 14:30:04 +0000 Subject: [PATCH 5/5] collections: more docs --- adaptors/collections.md | 106 +++++++++++++++------- docs/build/collections.md | 150 +++++++++++++++++++++++++++++++ sidebars-main.js | 1 + static/img/collections_admin.png | Bin 0 -> 37521 bytes 4 files changed, 223 insertions(+), 34 deletions(-) create mode 100644 docs/build/collections.md create mode 100644 static/img/collections_admin.png diff --git a/adaptors/collections.md b/adaptors/collections.md index ae4b4693e797..36c6caaf60bd 100644 --- a/adaptors/collections.md +++ b/adaptors/collections.md @@ -7,12 +7,6 @@ title: Collections Adaptor The Collections API provides access to a secure key/value store on the OpenFn Platform. It is designed for high performance over a large volume of data. -Use-cases include: - -- Storing mapping objects for use in workflows -- Buffering and aggregating high volumes of incoming data -- Caching and sharing state between workflows - Collections are secure, private datastores which are visible only to Workflows within a particular OpenFn Project. They can be created, managed and destroyed from the OpenFn Admin page. @@ -20,15 +14,29 @@ from the OpenFn Admin page. When running in the CLI, a Personal Access Token can be used to get access to the collection (generated from the app at /profile/tokens). +See the [Collections](documentation/build/collections) Platform Docs to learn +more about Collections. + +:::caution + +Collections must be created in the platform Admin page before they can be used. + +Refer to the [Collections Docs](documentation/build/collections) for details + +::: + ## The Collections Adaptor -The Collections adaptor is a special kind of adaptor. +The Collections API is inserted into all Steps through a special kind of +adaptor. -Uniquely, it is designed to be run _alongside_ other adaptors, and is injected -for you by the platform. +Uniquely, the Collections adaptor it is designed to be run _alongside_ other +adaptors, not by itself. It is injected into the runtime environment for you for +you by OpenFn. This makes the Collections API available to every Step in a +Workflow, regardless of which adaptor it is using. -This makes the Collections API available to every step in a Workflow, regardless -of which adaptor it is using. +If using the CLI run a workflow with Collections, refer to the +[CLI Usage](#cli-usage) guide below. ## Usage Guide @@ -63,7 +71,7 @@ a collection. Detailed usage examples are provided below. -### Set some data in a collection +### Set some data in a Collection The Collection API allows you to set a JSON object (or any primitive JS value) under a given key: @@ -119,7 +127,7 @@ In this example, the `createdDate`, `region` and `name` properties will be read from each value and assembled into a key-string, separated by dashes. This technique creates keys that are easily sorted by date. -### Getting data from a collection +### Getting data from a Collection To retrieve multiple items from a Collection, we generally recommend using the `each()` function. @@ -128,7 +136,7 @@ To retrieve multiple items from a Collection, we generally recommend using the overhead of downloading a large amount of data to the client. ```js -each('my-collection', '2024*', (state, value, key) => { +collections.each('my-collection', '2024*', (state, value, key) => { console.log(value); // No need to return state here }); @@ -139,7 +147,7 @@ pattern, or an object including different query strings. Check the API reference for a full listing. ```js -each( +collections.each( 'my-collection', { key: '2024*', created_after: '20240601' }, (state, value, key) => { @@ -153,13 +161,15 @@ there are returned values on the server, a `cursor` key will be written to `state.data`. ```js -each('my-collection', { key: '2024*', limit: 1000 }, (state, value, key) => { - console.log(value); -}).then(state => { - state.nextCursor = state.data.cursor; - // state.data.cursor now contains the cursor position - return state; -}); +collections + .each('my-collection', { key: '2024*', limit: 1000 }, (state, value, key) => { + console.log(value); + }) + .then(state => { + state.nextCursor = state.data.cursor; + // state.data.cursor now contains the cursor position + return state; + }); ``` You can fetch items individually with `get()`, which will be written to @@ -170,7 +180,7 @@ collections.get('my-collection', 'commcare-fhir-value-mappings').then(state => { state.mappings = state.data; return state; }); -each($.inputs, state => { +collecions.each($.inputs, state => { const mappedString = state.mappings[state.data.diagnosis]; state.resources ??= {}; state.resources[state.data.id] = mappedString; @@ -194,36 +204,64 @@ collections.get('my-collection', '2024*').then(state => { }); ``` -### Remove data from a collection +### Remove data from a Collection -You can remove an individual item by key: +You can remove an individual value by key: ```js collections.remove('my-collection', 'commcare-fhir-value-mappings'); ``` -You can also use the same query options as `get()` and `each()` to bulk delete: +You can also use patterns to delete multiple values at a time: ```js -collections.remove('my-collection', { createdBefore: '20240601' }); +collections.remove('my-collection', '2024*'); ``` -## Date Filters +## Filters, Limits & Cursors --TODO- +As well as filtering keys with patterns, you can filter by created date: -## Limits & Cursors +```js +collections.each( + 'my-collection', + { key: '2024*', createdAfter: '20240601' }, + (state, value, key) => { + console.log(value); + } +); +``` --TODO- +You can use `createdBefore` and `createdAfter` dates, which must be ISO 1806 +formatted strings. The `createdBefore` timestamp will match all dates less than +or equal to (<=) the _start_ of the provided date. Conversely, `createdAfter` +will match dates greater than or equal to the _end_ of the provided date. -## Collection Administration +By default, all matching values will be returned to you, but you can limit how +many items are returned in a single call: -Collections must be created in the platform Admin page before they can be used. +If a limit is set and there are more values waiting on the server, a `cursor` +will be written to `state.data`. You can pass this cursor back to the server in +the next query to resume from that position. -Collections can be removed from the Admin page. +```js +// request 10k values from the cursor position +collections.get('my-collection', { key: '*', limit: 10e3, cursor: $.cursor }); +fn(state => { + // Write the cursor (if any) back to state for next time + state.cursor = state.data.cursor; + return state; +}); +``` ## CLI usage +:::info + +Improved Collections support is coming to the CLI soon. + +::: + Collections are designed for close integration with the platform app, but can be used from the CLI too. diff --git a/docs/build/collections.md b/docs/build/collections.md new file mode 100644 index 000000000000..55c23331deaa --- /dev/null +++ b/docs/build/collections.md @@ -0,0 +1,150 @@ +--- +title: Collections +sidebar_label: Collections +--- + +Collections provides a high-volume, high-performance storage solution built into +OpenFn. + +Collections is suitable for buffering, caching and aggregating data from +Webhooks, storing large mapping files, and sharing state between workflows. + +Collections can be used to store a very large number of items (in the order of +millions). + +:::caution Collections Stability + +Collections is a new feature to OpenFn, in beta release since November 2024. + +We'd love to hear your feedback on +[community.openfn.org](https://community.openfn.org/) via email at +[support@openfn.org](mailto:support@openfn.org). + +::: + +## Use Cases + +### Buffering Data + +Many OpenFn integrations are triggered through a webhook, called from another +system based on some event. For example, every time a patient is registered, a +webhook calls into OpenFn to trigger a workflow and propagate the registration +event to other systems. + +Collections can be used as a buffer for these incoming events, saving the event +data on OpenFn and then processing a batch of events at the end of the day. This +is particularly useful in high volume events, or when limits are imposed on +upstream systems. + +With Collections, you can save each incoming event onto OpenFn, then run a +Workflow on a Cron trigger to process a batch of events in one go, and send on +aggregated, filtered or transformed results to the next system. + +### Mapping Structures + +A typical use-case is data integrations is to store large mapping objects. These +objects themselves are key-value pairs which map strings from one system into +matching strings from another system. For example, mapping medical codes into +SNOMED, or mapping city codes into human-readable strings, or mappings some +input string to a DHIS2 attribute code. + +These objects are often very large and hard to maintain, and can bloat job code. + +Instead, the mappings can be saved to a GitHub repository as a JSON object, and +uploaded to a collection using the CLI. + +## Collections Basics + +Data is stored in Collections as key-value pairs, where the key is a unique +identifier for some data (like a UUID, or timestamp). The value is always a +string - although JSON objects will be automatically serialized to a string +using the Collections API. + +Keys can be fetched in bulk and filtered by _pattern_. For example, the pattern +`2024*` will match all keys which start with `2024`. Designing keys to have an +efficient sort order is critical for high-volume Collections applications. + +The example below fetches values from the `openfn-patient-registrations` +collection and saves them onto state for further processing: + +```js +collections.get('openfn-patient-registrations', '2024*').then(state => { + state.registrationsThisYear = state.data; + return state; +}); +``` + +Every key permanently saves its creation date, so as well as fetching by +key-pattern, you can also filter keys by date. This example fetches all keys +created before 30th September 2024: + +```js +collections + .get('openfn-patient-registrations', '*', { createdBefore: '2024-09-30' }) + .then(state => { + state.registrationsThisYear = state.data; + return state; + }); +``` + +`collections.get` will download all matching values into memory. For large +values or high-volume value sets, it is more efficient to use +`collections.each`, which will stream each value into memory individually and +then discard it. + +```js +collections.each( + 'my-collection', + { key: '2024*', createdAfter: '20240601' }, + (state, value, key) => { + console.log(value); + } +); +``` + +New values are uploaded to a collection through `collections.set`: + +```js +collections.set('openfn-demo', 'commcare-fhir-value-mappings', { + current_smoker: { + system: 'http://snomed.info/sct', + code: '77176002', + display: 'Smoker', + }, + /* ... */ +}); +``` + +## Managing Collections + +Collections can be created, destroyed or renamed from the Admin menu. + +![Collections Admin Page](/img/collections_admin.png) + +Before it can be used, a collection must be created. Collection names must be +unique to the deployment, so we recommend using your organisation (and maybe +project) as a prefix, ie, `openfn-demo`. + +## Using Collections + +Collections are available to all Workflows via a simple high-level interface. + +:::caution + +A Collection must be created in the admin interface before it can be used. + +::: + +The Collections API provides four basic verbs: + +- [`collections.get()`](adaptors/packages/collections-docs#collections_get) + downloads values matching a key or key pattern. +- [`collections.each()`](adaptors/packages/collections-docs#collections_each) + efficiently iterates over a range of items in a collection. +- [`collections.set()`](adaptors/packages/collections-docs#collections_set) + uploads values to a collection. +- [`collections.remove()`](adaptors/packages/collections-docs#collections_remove) + will remove values by key or key pattern. + +The Collection API is backed by a special adaptor: see the +[Collections Adaptor API](adaptors/collections) for more details. diff --git a/sidebars-main.js b/sidebars-main.js index c9f9530a81a5..73552380fb76 100644 --- a/sidebars-main.js +++ b/sidebars-main.js @@ -64,6 +64,7 @@ module.exports = { 'build/ai-assistant', 'build/paths', 'build/credentials', + 'build/collections', 'build/limits', 'build/editing-locally', 'build/working-with-branches', diff --git a/static/img/collections_admin.png b/static/img/collections_admin.png new file mode 100644 index 0000000000000000000000000000000000000000..d86a0dd63527db5dd89ae8c8d7da5abeac4ab04e GIT binary patch literal 37521 zcmeFZbyQr-wl7SS;F}OEXc`E?8h1;O;1FCJf;8SV?vey|cMIER7Ff*OpF@g1@Hh+K6;Aq2#BRW0iu7!83FRgkDed^NeEuR{St^j&^+9) zA3ggW1^{t_zv2-<{M}zP4<#`^dW?VugbBdS1jJtfVJ>hRdH-2fBM^W1z4-kn3dA0e z{}zgfNqr(^0y8pznK^*`3`{IsjEr2245W-4Tukg-tegP#qwoLV=r>YS&N6`FX(TB4 zNlZ|X)Z7xTZ)6HZK(J463FQ@SeNWh?r7oO<{ejzuOD`K;2N&BSU-6xQ=O>!-t6@+{f}(m6h}9_oYOwB|Rh?hepqH;1Zr4_Y{Xp_hNbbdI}J9!+QL@#CfC$ zWfcOCZtj=Or+9=`TN+%`+-) zBDol@#T*MVgoC~`!WNclGrF99tfDhqq)T|Mh(3zDb0)UuPlNw@{G{r=dGBsPP4F-x zsT70){>5GJbN>6uZQ}hsv;Ez9=H5G3gggh!2A5d2pMVnD8!4z*t4K+5>B3=PZ9TXS z6l@POe`qlT9)5dsZCw+nHK`8Nz{rdjv|rZ*A~n+E1u3&iF-VyULJf^X9W9~qj?xOc zjwZUCdLVv2WFC7i000KH)+V)wnVMN~+4F*a<8lG2DHi6JC%Cph$vnODHJ| zm<7y0Cv0zI%LL*>Cgriz)8~>C`uGw*=4&26?7X$*{lm3lAn7NeH z-{H-y{*nS94|;oTb9zQF13e5z|IazBtc7g>kiQuEw>hj79L%Bga!@O{jioMB*cNJL zP4>?adb)qlZ*F60`nx)My7W*}C=4LA0!n54mm(j!+~0FNh`_)IX8t=DAnbpkv^LWJ zhp_&Iw}&^stMku{0NMYJ`!CdgtNU+afJ#b=O9-xO^T3{%5HIMVd@en>u8|(s?iiJ6&E7y3_7VrEv>+Ge`Y2Pgm>Yy{x2 zvN1v#IH0<8z|Balx`g{CCt3orjbM zpa+^<)W`}b-{E)CpFK(*YVqgOpO2F-X#rLFsC6|A&vp?bgh1hD>mrE92d zW&j07kH6IQZ|O$=Mip3?S#_B7SvcsR`hY&LaB@7fpAI`61EW40C#SY93loR-zoJ{g z^{wr+EukL_067A(0@U;O6h->(cSBMAE47^=^r001fzdHC(lIjpe+5SWSB2>x#*Dw! zn1}xVClj9E1phS10Qvq*0|qZ(ETsSYVEC8J9)_L&hrhqt;{Ra@0Q7$f`5(#mKjQk2 zxc)~H_#YAfN4x$buK$q){zt_B(XRh%;zIt1IR!NXRzY@vu~hPXG8{0pp6f`62qD}* z{C#i8dPqSs7ge=FKtREIxE~?JCEx*xh}L3K!iXCv$S(=FsTix`5D-Wa#DqR5*iY@u z8feHH+&@3idaEt??YZz%VK1fkpYW$1Q-70tCi1MHPE8pGs~A0lCr_mm*m9`lk8bIX zs$ml&ipz$o{b>G_^5w~=S5JScV6h?T9k^kB40%He+B&_xXh}%0T3_iCtF~OX+iPWb zg--gVlBU)TEfL@b0YZocc?c0+)FH&>4n6~7Uy4y468>!fP(A$qkAr^;@^2IA@z4Bk zPaNap8Sw(7T|b3xXsJReg6JMf^O(&7Qyf|w@FmFQyo%vm`0=p$@qS{LyqiyBm=i;9 ztkwFm^cly))(65Lw%i!*%@;5&LrR_j7KWo;{8!4V4r$`g= z%UH1@x3<=dGrajT1HLJaf0rIZY`^8lryjp$V#w?%m!t3wTU@c?V|zhbe&Jhes#oIA z-JA6pRZVf?+XN
  • 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

    yxU?8vPw|m!oE&Lo7lGixT2=! zjOy`=a-@do4ZLi(wNsG~Kwm!gZhD09)Y-$u9Cvq+#Of(mTSG~lnNAK(6vpOYLc0J7 z8+2_gG^_OqquIF6hLwp@gdeK9(Z

    COPx>ZgF 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 literal 0 HcmV?d00001