mirror of
https://github.com/mozilla/gecko-dev.git
synced 2024-11-23 04:41:11 +00:00
Bug 1927569
- Rust component JS topic guides, r=bgruber
Added JS topic guides and also updated the existing Swift/JS ones a bit. I didn't add a guide for remote settings, since I don't think we want to encourage users to use this one over the official client. Split up the notes at the begining into prerequites and notes on async. My hope is that the async notes can go away once we start making our components async. Differential Revision: https://phabricator.services.mozilla.com/D228481
This commit is contained in:
parent
2b0abf3bad
commit
726d243f2f
@ -7,6 +7,20 @@ myst:
|
||||
|
||||
The `relevancy` component tracks the user's interests locally, without sharing any data over the network. The component currently supports building an interest vector based on the URLs they visit.
|
||||
|
||||
## Prerequisites
|
||||
|
||||
That {doc}`viaduct` must be initialized during application startup.
|
||||
|
||||
## Async
|
||||
|
||||
The Relevancy API is synchronous, which means calling it directly will block the current
|
||||
thread. To deal with this, all current consumers wrap the API in order to make it async. For
|
||||
details on this wrapping, see the consumer code itself.
|
||||
|
||||
On JS, this wrapping is handled automatically by UniFFI. See
|
||||
https://searchfox.org/mozilla-central/source/toolkit/components/uniffi-bindgen-gecko-js/config.toml
|
||||
for details on which functions/methods are wrapped to be async.
|
||||
|
||||
## Setting up the store
|
||||
|
||||
To use the `RelevancyStore` in either Kotlin or Swift, you need to import the relevant classes and data types from the `MozillaAppServices` library.
|
||||
@ -24,19 +38,13 @@ import MozillaAppServices
|
||||
|
||||
let store = RelevancyStore(dbPath: "path/to/database")
|
||||
```
|
||||
:::
|
||||
|
||||
```js
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
RelevancyStore: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
});
|
||||
|
||||
|
||||
To work with the RelevancyStore, you need to create an instance using a database path where the user’s interest data will be stored:
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
val store = RelevancyStore(dbPath)
|
||||
```
|
||||
|
||||
```swift
|
||||
let store = RelevancyStore(dbPath: "path/to/database")
|
||||
const store = RelevancyStore.init(dbPath);
|
||||
```
|
||||
:::
|
||||
|
||||
@ -59,6 +67,11 @@ val interestVector = store.ingest(topUrlsByFrequency)
|
||||
let topUrlsByFrequency = ["https://example.com", "https://another-example.com"]
|
||||
let interestVector = store.ingest(topUrlsByFrequency)
|
||||
```
|
||||
|
||||
```js
|
||||
const topUrlsByFrequency = ["https://example.com", "https://another-example.com"];
|
||||
const interestVector = await store.ingest(topUrlsByFrequency);
|
||||
```
|
||||
:::
|
||||
|
||||
* `topUrlsByFrequency`: A list of URLs ranked by how often and recently the user has visited them. This data is used to build the user's interest vector.
|
||||
|
@ -7,13 +7,15 @@ myst:
|
||||
|
||||
The API for the Remote Settings can be found in the Mozilla Rust components [Kotlin API Reference](https://mozilla.github.io/application-services/kotlin/kotlin-components-docs/mozilla.appservices.remotesettings/index.html) and [Swift API Reference](https://mozilla.github.io/application-services/swift/Classes/RemoteSettings.html).
|
||||
|
||||
```{note}
|
||||
Make sure you initialize {doc}`viaduct` for this component.
|
||||
```
|
||||
## Prerequisites
|
||||
|
||||
```{warning}
|
||||
The remote settings code is synchronous, which means it needs to be wrapped in the asynchronous primitive of the target language you are using.
|
||||
```
|
||||
That {doc}`viaduct` must be initialized during application startup.
|
||||
|
||||
## Async
|
||||
|
||||
The Remote Settings API is synchronous, which means calling it directly will block the current
|
||||
thread. To deal with this, all current consumers wrap the API in order to make it async. For
|
||||
details on this wrapping, see the consumer code itself.
|
||||
|
||||
## Importing items
|
||||
|
||||
|
@ -7,14 +7,19 @@ myst:
|
||||
|
||||
The API for the `SuggestStore` can be found in the [MozillaComponents Kotlin documentation](https://mozilla.github.io/application-services/kotlin/kotlin-components-docs/mozilla.appservices.suggest/-suggest-store/index.html).
|
||||
|
||||
```{note}
|
||||
Make sure you initialize {doc}`viaduct` for this component.
|
||||
```
|
||||
## Prerequisites
|
||||
|
||||
```{warning}
|
||||
The `SuggestStore` is synchronous, which means it needs to be wrapped in the asynchronous primitive of the target language you are using.
|
||||
```
|
||||
That {doc}`viaduct` must be initialized during application startup.
|
||||
|
||||
## Async
|
||||
|
||||
The Suggest API is synchronous, which means calling it directly will block the current
|
||||
thread. To deal with this, all current consumers wrap the API in order to make it async. For
|
||||
details on this wrapping, see the consumer code itself.
|
||||
|
||||
On JS, this wrapping is handled automatically by UniFFI. See
|
||||
https://searchfox.org/mozilla-central/source/toolkit/components/uniffi-bindgen-gecko-js/config.toml
|
||||
for details on which functions/methods are wrapped to be async.
|
||||
|
||||
## Setting up the store
|
||||
|
||||
@ -35,6 +40,20 @@ import mozilla.appservices.suggest.SuggestionQuery
|
||||
```swift
|
||||
import MozillaAppServices
|
||||
```
|
||||
|
||||
```js
|
||||
ChromeUtils.defineESModuleGetters(lazy, {
|
||||
RemoteSettingsServer: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestApiException: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestIngestionConstraints: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestStore: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestStoreBuilder: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
Suggestion: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestionProvider: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
SuggestionQuery: "resource://gre/modules/RustSuggest.sys.mjs",
|
||||
});
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
Create a `SuggestStore` as a singleton. You do this via the `SuggestStoreBuilder`, which returns a `SuggestStore`. No I/O or network requests are performed during construction, which makes this safe to do at any point in the application startup:
|
||||
@ -56,6 +75,15 @@ let store: SuggestStore = {
|
||||
return storeBuilder.build()
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
const store: SuggestStore = SuggestStoreBuilder()
|
||||
.dataPath(pathForSuggestDatabase)
|
||||
.remoteSettingsServer(remoteSettingsServer)
|
||||
.build();
|
||||
}
|
||||
|
||||
:::
|
||||
|
||||
* You need to set the `dataPath`, which is the path (the SQLite location) where you store your suggestions.
|
||||
@ -75,18 +103,26 @@ Ingest with `SuggestIngestionConstraints(emptyOnly=true)` shortly after each sta
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
store.value.ingest(SuggestIngestionConstraints(
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly = true,
|
||||
providers = listOf(SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER)
|
||||
))
|
||||
```
|
||||
|
||||
```swift
|
||||
store.value.ingest(SuggestIngestionConstraints(
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly: true,
|
||||
providers: [.AMP_MOBILE, .WIKIPEDIA, .WEATHER]
|
||||
))
|
||||
```
|
||||
|
||||
```js
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly: true,
|
||||
providers: [SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER]
|
||||
))
|
||||
```
|
||||
|
||||
:::
|
||||
|
||||
### Periodically
|
||||
@ -95,11 +131,25 @@ Ingest with `SuggestIngestionConstraints(emptyOnly=false)` on a regular schedule
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
store.value.ingest(SuggestIngestionConstraints(emptyOnly = false))
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly = false,
|
||||
providers = listOf(SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER)
|
||||
))
|
||||
```
|
||||
|
||||
```swift
|
||||
store.value.ingest(SuggestIngestionConstraints(emptyOnly: false))
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly: false,
|
||||
providers: [.AMP_MOBILE, .WIKIPEDIA, .WEATHER]
|
||||
))
|
||||
```
|
||||
|
||||
|
||||
```js
|
||||
store.ingest(SuggestIngestionConstraints(
|
||||
emptyOnly: false,
|
||||
providers: [SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER]
|
||||
))
|
||||
```
|
||||
:::
|
||||
|
||||
@ -109,7 +159,7 @@ Call `SuggestStore::query` to fetch suggestions for the suggest bar. The `provid
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
store.value.query(
|
||||
store.query(
|
||||
SuggestionQuery(
|
||||
keyword = text,
|
||||
providers = listOf(SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER),
|
||||
@ -119,7 +169,7 @@ store.value.query(
|
||||
```
|
||||
|
||||
```swift
|
||||
store.value.query(
|
||||
store.query(
|
||||
SuggestionQuery(
|
||||
keyword: text,
|
||||
providers: [.AMP_MOBILE, .WIKIPEDIA, .WEATHER],
|
||||
@ -127,32 +177,50 @@ store.value.query(
|
||||
)
|
||||
)
|
||||
```
|
||||
|
||||
```js
|
||||
store.query(
|
||||
SuggestionQuery(
|
||||
keyword = text,
|
||||
providers = [SuggestionProvider.AMP_MOBILE, SuggestionProvider.WIKIPEDIA, SuggestionProvider.WEATHER],
|
||||
limit = MAX_NUM_OF_FIREFOX_SUGGESTIONS,
|
||||
),
|
||||
)
|
||||
```
|
||||
:::
|
||||
|
||||
## Interrupt querying
|
||||
|
||||
Call `SuggestStore::Interrupt` with `InterruptKind::Read` to interrupt any in-progress queries when the user cancels a query and before running the next query.
|
||||
Call `interrupt()` with `InterruptKind::Read` to interrupt any in-progress queries when the user cancels a query and before running the next query.
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
store.value.interrupt()
|
||||
store.interrupt(InterruptKind.READ)
|
||||
```
|
||||
|
||||
```swift
|
||||
store.value.interrupt()
|
||||
store.interrupt(kind: InterruptKind.READ)
|
||||
```
|
||||
|
||||
```js
|
||||
store.interrupt(InterruptKind.READ)
|
||||
```
|
||||
:::
|
||||
|
||||
## Shutdown the store
|
||||
|
||||
On shutdown, call `SuggestStore::Interrupt` with `InterruptKind::ReadWrite` to interrupt any in-progress ingestion and queries.
|
||||
On shutdown, call `interrupt()` with `InterruptKind::ReadWrite` to interrupt any in-progress ingestion in addition to queries.
|
||||
|
||||
:::{tab-set-code}
|
||||
```kotlin
|
||||
store.value.interrupt()
|
||||
store.interrupt(InterruptKind.READ_WRITE)
|
||||
```
|
||||
|
||||
```swift
|
||||
store.value.interrupt()
|
||||
store.interrupt(kind: InterruptKind.READ_WRITE)
|
||||
```
|
||||
|
||||
```js
|
||||
store.interrupt(InterruptKind.READ_WRITE)
|
||||
```
|
||||
:::
|
||||
|
@ -2,6 +2,9 @@
|
||||
|
||||
`Viaduct` initialization is required for all platforms and for multiple components. The [README](https://github.com/mozilla/application-services/blob/main/components/viaduct/README.md) explains the component in more detail.
|
||||
|
||||
Firefox Desktop, Firefox Android, and Firefox iOS all already initialize viaduct. You only need to
|
||||
take action if you want to use the Rust components on a new application.
|
||||
|
||||
There are 3 different options to use `viaduct`:
|
||||
|
||||
* Any `libxul` based can ignore initialization, since it's handled by `libxul`.
|
||||
|
@ -11,7 +11,9 @@
|
||||
|
||||
|
||||
[suggest.async_wrappers]
|
||||
# All functions/methods are wrapped to be async by default and must be `await`ed.
|
||||
enable = true
|
||||
# These are exceptions to the async wrapping. These functions must not be `await`ed.
|
||||
main_thread = [
|
||||
"raw_suggestion_url_matches",
|
||||
"SuggestStore",
|
||||
@ -25,7 +27,9 @@ main_thread = [
|
||||
]
|
||||
|
||||
[relevancy.async_wrappers]
|
||||
# All functions/methods are wrapped to be async by default and must be `await`ed.
|
||||
enable = true
|
||||
# These are exceptions to the async wrapping. These functions must not be `await`ed.
|
||||
main_thread = [
|
||||
"RelevancyStore",
|
||||
"RelevancyStore.close",
|
||||
@ -34,21 +38,19 @@ main_thread = [
|
||||
]
|
||||
|
||||
[remote_settings.async_wrappers]
|
||||
# All functions/methods are wrapped to be async by default and must be `await`ed.
|
||||
enable = true
|
||||
# These are exceptions to the async wrapping. These functions must not be `await`ed.
|
||||
main_thread = [
|
||||
"RemoteSettings",
|
||||
]
|
||||
|
||||
[uniffi_fixture_callbacks.async_wrappers]
|
||||
enable = true
|
||||
main_thread = [
|
||||
"log_even_numbers_main_thread",
|
||||
]
|
||||
|
||||
[error_support.async_wrappers]
|
||||
# All functions/methods are wrapped to be async by default and must be `await`ed.
|
||||
enable = true
|
||||
|
||||
[tabs.async_wrappers]
|
||||
# All functions/methods are wrapped to be async by default and must be `await`ed.
|
||||
enable = true
|
||||
|
||||
[arithmetical.async_wrappers]
|
||||
@ -57,6 +59,12 @@ enable = true
|
||||
[uniffi_custom_types.async_wrappers]
|
||||
enable = true
|
||||
|
||||
[uniffi_fixture_callbacks.async_wrappers]
|
||||
enable = true
|
||||
main_thread = [
|
||||
"log_even_numbers_main_thread",
|
||||
]
|
||||
|
||||
[uniffi_fixture_external_types.async_wrappers]
|
||||
enable = true
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user