diff --git a/docs/python/how-to-guides/create-plugins.md b/docs/python/how-to-guides/create-plugins.md index 05024ea003a..5c6abb84a6f 100644 --- a/docs/python/how-to-guides/create-plugins.md +++ b/docs/python/how-to-guides/create-plugins.md @@ -25,7 +25,7 @@ ExampleServicePlugin/ └── pyproject.toml └── example_plugin_server/ └── __init__.py -└── server/ +└── client/ └── pyproject.toml └── example_plugin_client/ └── __init__.py @@ -86,7 +86,7 @@ class ExampleService: def hello_string(self, data: str) -> str: """Returns a string containing the input data.""" - return f"Hello client. You said: {data}" + return f"Hello client. You said: {data}" def hello_table(self, table: Table, data: str) -> Table: """Returns a table generated from the input table and the input data.""" @@ -201,7 +201,7 @@ class ExampleService: def hello_string(self, data: str) -> str: """Returns a string containing the input data.""" - return f"Hello client. You said: {data}" + return f"Hello client. You said: {data}" def hello_table(self, table: Table, data: str) -> Table: """Returns a table generated from the input table and the input data.""" @@ -427,7 +427,7 @@ dependencies = ["pydeephaven>=0.36.1", "pandas"] ## Use the plugin -Once you have completed all of the client—and server-side wiring, you can test the plugin. The following subsections cover testing the server using different launch methods. +Once you have completed all of the client- and server-side wiring, you can test the plugin. The following subsections cover testing the server using different launch methods. ### Installation @@ -463,7 +463,7 @@ RUN pip install /server The following Docker Compose file runs Deephaven using the image built by the above Dockerfile: > [!IMPORTANT] -> The Dockerfile below sets the pre-shared key to `YOUR_PASSWORD_HERE` for demonstration purposes. The client needs this key when connecting to the server. It is recommended that this key be changed to something more secure. +> The Docker Compose file below sets the pre-shared key to `YOUR_PASSWORD_HERE` for demonstration purposes. The client needs this key when connecting to the server. It is recommended that this key be changed to something more secure. ```yaml services: @@ -487,8 +487,12 @@ If running Deephaven from Python, the following Python script will start a Deeph ```python skip-test import sys +from deephaven_server import Server from example_plugin_server import ExampleService +# Start the Deephaven server +server = Server(port=10000) +server.start() example_service = ExampleService() @@ -573,6 +577,82 @@ print(table_result.to_arrow().to_pandas()) session.close() ``` +## Share plugin objects between sessions + +Plugin objects created in one session can be shared with other sessions using the [`publish`](../reference/client-api/session/publish.md) and [`fetch`](../reference/client-api/session/fetch.md) methods. This is useful when you want multiple client sessions to interact with the same server-side plugin object. + +### Publishing a plugin object + +To share a plugin object, first fetch it to get an export ticket, then publish it to a shared ticket: + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket + +# Connect to the server +session = Session( + auth_type="io.deephaven.authentication.psk.PskAuthenticationHandler", + auth_token="YOUR_PASSWORD_HERE", +) + +# Get the plugin object ticket +example_service_ticket = session.exportable_objects["example_service"] + +# Create a plugin client +plugin_client = session.plugin_client(example_service_ticket) + +# Fetch the plugin object to get an export ticket +export_ticket = session.fetch(plugin_client) + +# Publish to a shared ticket +shared_ticket = SharedTicket.random_ticket() +session.publish(export_ticket, shared_ticket) + +# Now other sessions can use this shared_ticket to access the same plugin object +``` + +### Fetching a shared plugin object + +Another session can fetch the shared plugin object using the shared ticket: + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import ServerObject, SharedTicket + +# Connect to the server +sub_session = Session( + auth_type="io.deephaven.authentication.psk.PskAuthenticationHandler", + auth_token="YOUR_PASSWORD_HERE", +) + +# Use the shared ticket from the publishing session +# (In practice, you would pass this ticket between sessions) +shared_ticket = SharedTicket.random_ticket() # Use the actual shared ticket + +# Create a ServerObject reference with the appropriate type +server_obj = ServerObject( + type="example_plugin_server.ExampleService", ticket=shared_ticket +) + +# Create a plugin client to interact with the shared object +sub_plugin_client = sub_session.plugin_client(server_obj) + +# Now you can use the plugin client as usual +from example_plugin_client import ExampleServiceProxy + +example_service = ExampleServiceProxy(sub_plugin_client) + +result = example_service.hello_string("Hello from another session!") +print(result) + +sub_session.close() +``` + +> [!IMPORTANT] +> Shared tickets remain valid only as long as the publishing session keeps the object alive. When the publishing session closes or releases the object, the shared ticket becomes invalid. + ## Related documentation - [Install and use plugins](./install-use-plugins.md) +- [`publish`](../reference/client-api/session/publish.md) - Publish server objects to shared tickets +- [`fetch`](../reference/client-api/session/fetch.md) - Fetch server objects by ticket diff --git a/docs/python/reference/client-api/session/fetch-table.md b/docs/python/reference/client-api/session/fetch-table.md new file mode 100644 index 00000000000..78348f2c384 --- /dev/null +++ b/docs/python/reference/client-api/session/fetch-table.md @@ -0,0 +1,59 @@ +--- +title: fetch_table +--- + +The `fetch_table` method fetches a table by [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket). + +This is a convenience method specifically for tables. For fetching other types of server objects (such as plots, pandas DataFrames, or plugin objects), use the generic [`fetch`](./fetch.md) method. + +> [!NOTE] +> If the remote table is closed or its owner session is closed, the ticket becomes invalid. + +## Syntax + +```python syntax +fetch_table(ticket: SharedTicket) -> Table +``` + +## Parameters + + + + +A [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket) object. + + + + +## Returns + +A Table object. + +## Examples + +The following example fetches a table that was published to a shared ticket by another session. + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket + +# Assume another session published a table to this shared ticket +# (In practice, you would get this ticket from the publishing session) +shared_ticket = SharedTicket.random_ticket() # Use the actual shared ticket + +# Connect and fetch the table +session = Session(host="localhost", port=10000) +table = session.fetch_table(shared_ticket) + +session.close() +``` + +For a complete example showing how to use `fetch_table` with tables published from another session, see the Barrage [`subscribe`](../../data-import-export/barrage/subscribe.md) documentation. + +## Related documentation + +- [`publish_table`](./publish-table.md) +- [`fetch`](./fetch.md) +- [`publish`](./publish.md) +- [`subscribe`](../../data-import-export/barrage/subscribe.md) +- [Session API](/core/client-api/python/code/pydeephaven.session.html#pydeephaven.session.Session.fetch_table) diff --git a/docs/python/reference/client-api/session/fetch.md b/docs/python/reference/client-api/session/fetch.md new file mode 100644 index 00000000000..e55d9f7bc5c --- /dev/null +++ b/docs/python/reference/client-api/session/fetch.md @@ -0,0 +1,131 @@ +--- +title: fetch +--- + +The `fetch` method fetches a server object by ticket and returns an [`ExportTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.ExportTicket). This is a low-level method that can be used to fetch any server object (not just tables). + +The ticket represents a fetchable server object, such as a [`PluginClient`](/core/client-api/python/code/pydeephaven.experimental.plugin_client.html#pydeephaven.experimental.plugin_client.PluginClient) or [`Fetchable`](/core/client-api/python/code/pydeephaven.experimental.plugin_client.html#pydeephaven.experimental.plugin_client.Fetchable). This method is used together with the [`publish`](./publish.md) method to share server objects between sessions. + +> [!NOTE] +> For tables specifically, use the higher-level [`fetch_table`](./fetch-table.md) method instead. + +## Syntax + +```python syntax +fetch(ticket: Ticket) -> ExportTicket +``` + +## Parameters + + + + +The ticket representing a fetchable server object. + + + + +## Returns + +An [`ExportTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.ExportTicket) object that can be used to reference the fetched server object. + +## Examples + +### Fetching and publishing a Figure object + +The following example fetches a Figure (plot) object and publishes it to a shared ticket. + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket, ServerObject + +# Create a session and generate a plot +session = Session(host="localhost", port=10000) +session.run_script(""" +from deephaven.plot.figure import Figure +from deephaven import empty_table + +source = empty_table(20).update([ + "X = 0.1 * i", + "Y = randomDouble(0.0, 5.0)" +]) + +plot = Figure().plot_xy( + series_name="Random numbers", + t=source, + x="X", + y="Y" +).show() +""") + +# Get the plot object from the session +plot_obj = session.exportable_objects["plot"] + +# Create a plugin client to interact with the plot +plugin_client = session.plugin_client(plot_obj) + +# Fetch the plugin object to get an export ticket +export_ticket = session.fetch(plugin_client) + +# Now you can publish this export ticket to share it with other sessions +shared_ticket = SharedTicket.random_ticket() +session.publish(export_ticket, shared_ticket) + +plugin_client.close() +session.close() +``` + +### Fetching a table using generic fetch + +While [`fetch_table`](./fetch-table.md) is recommended for tables, you can also use the generic `fetch` method: + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import ScopeTicket + +# Create a session and table +session = Session(host="localhost", port=10000) +session.run_script("source = empty_table(20).update('X = i')") + +# Fetch the table as an export ticket using the generic fetch method +export_ticket = session.fetch(ScopeTicket.scope_ticket("source")) + +# The export_ticket can now be used to reference the table +# or published to a shared ticket for other sessions to access + +session.close() +``` + +### Fetching a shared plugin object + +The following example shows how to fetch a plugin object that was published to a shared ticket by another session. + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket, ServerObject + +# Assume another session published a Figure to this shared ticket +shared_ticket = SharedTicket.random_ticket() # Use the actual shared ticket + +# Connect to the session and fetch the shared object +session = Session(host="localhost", port=10000) + +# Create a ServerObject reference with the appropriate type +server_obj = ServerObject(type="Figure", ticket=shared_ticket) + +# Create a plugin client to interact with the shared Figure +plugin_client = session.plugin_client(server_obj) + +# You can now interact with the Figure through the plugin client +payload, refs = next(plugin_client.resp_stream) + +plugin_client.close() +session.close() +``` + +## Related documentation + +- [`publish`](./publish.md) +- [`fetch_table`](./fetch-table.md) +- [`publish_table`](./publish-table.md) +- [Session API](/core/client-api/python/code/pydeephaven.session.html#pydeephaven.session.Session.fetch) diff --git a/docs/python/reference/client-api/session/publish-table.md b/docs/python/reference/client-api/session/publish-table.md new file mode 100644 index 00000000000..8329d4b946e --- /dev/null +++ b/docs/python/reference/client-api/session/publish-table.md @@ -0,0 +1,68 @@ +--- +title: publish_table +--- + +The `publish_table` method publishes a table to a given [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket). The ticket can then be used by another session to fetch the table. + +The shared ticket can be fetched by other sessions to access the table as long as the table is not released. When the table is released either through an explicit call of the `close` method on it, implicitly through garbage collection, or through the closing of the publishing session, the shared ticket will no longer be valid. + +This is a convenience method specifically for tables. For publishing other types of server objects (such as plots, pandas DataFrames, or plugin objects), use the generic [`publish`](./publish.md) method. + +## Syntax + +```python syntax +publish_table(ticket: SharedTicket, table: Table) -> None +``` + +## Parameters + + + + +A [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket) object. + + + + +A Table object to publish. + + + + +## Returns + +This method returns `None`. + +## Examples + +The following example creates a table and publishes it to a shared ticket so that other sessions can access it. + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket + +# Create a session and table +pub_session = Session(host="localhost", port=10000) +table = pub_session.empty_table(1000).update(["X = i", "Y = 2*i"]) + +# Create and publish to a shared ticket +shared_ticket = SharedTicket.random_ticket() +pub_session.publish_table(shared_ticket, table) + +# Another session can now fetch this table +sub_session = Session(host="localhost", port=10000) +fetched_table = sub_session.fetch_table(shared_ticket) + +sub_session.close() +pub_session.close() +``` + +For a complete example showing how to use `publish_table` with Barrage sessions, see the Barrage [`subscribe`](../../data-import-export/barrage/subscribe.md) documentation. + +## Related documentation + +- [`fetch_table`](./fetch-table.md) +- [`publish`](./publish.md) +- [`fetch`](./fetch.md) +- [`subscribe`](../../data-import-export/barrage/subscribe.md) +- [`Session`](/core/client-api/python/code/pydeephaven.session.html#pydeephaven.session.Session) diff --git a/docs/python/reference/client-api/session/publish.md b/docs/python/reference/client-api/session/publish.md new file mode 100644 index 00000000000..58db38dfd9a --- /dev/null +++ b/docs/python/reference/client-api/session/publish.md @@ -0,0 +1,130 @@ +--- +title: publish +--- + +The `publish` method publishes a source ticket to a result ticket. This is a low-level method that can be used to publish any server object (not just tables) to a shared ticket. + +The source ticket represents a previously fetched server object to be published, and the result ticket (typically a [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket)) is the ticket to publish to. The result ticket can then be fetched by other sessions to access the object as long as the object is not released. + +This method is used together with the [`fetch`](./fetch.md) method to share server objects between sessions. + +> [!NOTE] +> For tables specifically, use the higher-level [`publish_table`](./publish-table.md) method instead. + +> [!IMPORTANT] +> Shared tickets have a life cycle tied to the source. Tickets can be fetched by other Deephaven sessions to access the object _only_ as long as the object is not released. When the object is released either through an explicit call of the `release` method, implicitly through garbage collection, or through the closing of the publishing session, the shared ticket will no longer be valid. + +## Syntax + +```python syntax +publish(source_ticket: Ticket, result_ticket: Ticket) -> None +``` + +## Parameters + + + + +The source ticket to publish from. + + + + +The result ticket to publish to, typically a [`SharedTicket`](/core/client-api/python/code/pydeephaven.ticket.html#pydeephaven.ticket.SharedTicket). + + + + +## Returns + +This method returns `None`. + +## Examples + +### Publishing a Figure object + +The following example publishes a Figure (plot) object to a shared ticket so it can be accessed by another session. + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket, ServerObject + +# Create a session and generate a plot +session = Session(host="localhost", port=10000) +session.run_script(""" +from deephaven.plot.figure import Figure +from deephaven import empty_table + +source = empty_table(20).update([ + "X = 0.1 * i", + "Y = randomDouble(0.0, 5.0)" +]) + +plot = Figure().plot_xy( + series_name="Random numbers", + t=source, + x="X", + y="Y" +).show() +""") + +# Get the plot object from the session +plot_obj = session.exportable_objects["plot"] + +# Create a plugin client to interact with the plot +plugin_client = session.plugin_client(plot_obj) + +# Fetch the plugin object to get an export ticket +export_ticket = session.fetch(plugin_client) + +# Publish the plot to a shared ticket +shared_ticket = SharedTicket.random_ticket() +session.publish(export_ticket, shared_ticket) + +# Another session can now fetch this plot +sub_session = Session(host="localhost", port=10000) +server_obj = ServerObject(type="Figure", ticket=shared_ticket) +sub_plugin_client = sub_session.plugin_client(server_obj) + +# The subscriber session can now interact with the plot +payload, refs = next(sub_plugin_client.resp_stream) + +sub_plugin_client.close() +sub_session.close() +plugin_client.close() +session.close() +``` + +### Publishing a table using generic publish + +While [`publish_table`](./publish-table.md) is recommended for tables, you can also use the generic `publish` method: + +```python skip-test +from pydeephaven import Session +from pydeephaven.ticket import SharedTicket, ScopeTicket + +# Create a session and table +session = Session(host="localhost", port=10000) +session.run_script("source = empty_table(20).update('X = i')") + +# Fetch the table as an export ticket +export_ticket = session.fetch(ScopeTicket.scope_ticket("source")) + +# Publish using the generic publish method +shared_ticket = SharedTicket.random_ticket() +session.publish(export_ticket, shared_ticket) + +# Another session can fetch this table +sub_session = Session(host="localhost", port=10000) +table = sub_session.fetch_table(shared_ticket) + +sub_session.close() +session.close() +``` + +## Related documentation + +- [`fetch`](./fetch.md) +- [`publish_table`](./publish-table.md) +- [`fetch_table`](./fetch-table.md) +- [Session API](/core/client-api/python/code/pydeephaven.session.html) diff --git a/docs/python/reference/data-import-export/barrage/subscribe.md b/docs/python/reference/data-import-export/barrage/subscribe.md index a6ea51a49ed..bdf7b16ef17 100644 --- a/docs/python/reference/data-import-export/barrage/subscribe.md +++ b/docs/python/reference/data-import-export/barrage/subscribe.md @@ -29,7 +29,7 @@ A `Table` that is a subscribed to the remote table. ## Examples -The following example installs the Deephaven Python Client ([`pydeephaven`](/core/client-api/python/)) on a Deephaven server running on port `10001`. It also starts a Deephaven server running locally on port `10000` with [anonymous authentication](../../../how-to-guides/authentication/auth-anon.md). +The following example uses the Deephaven Python Client ([`pydeephaven`](/core/client-api/python/)) to connect to a Deephaven server running on port `10000` with [PSK authentication](../../../how-to-guides/authentication/auth-psk.md). Next, the client creates a table on the server on port `10000`. A shared ticket is created that publishes the table, which allows it to be shared with other sessions. Finally, a Barrage session is started that listens to the server on port `10000`, and a new local table that is subscribed to the shared ticket's table is obtained. @@ -99,4 +99,6 @@ services: ## Related documentation +- [`fetch_table`](../../client-api/session/fetch-table.md) +- [`publish_table`](../../client-api/session/publish-table.md) - [Pydoc](/core/pydoc/code/deephaven.barrage.html#deephaven.barrage.BarrageSession.subscribe) diff --git a/docs/python/sidebar.json b/docs/python/sidebar.json index f06e86a8676..76218b031ed 100644 --- a/docs/python/sidebar.json +++ b/docs/python/sidebar.json @@ -1450,6 +1450,27 @@ } ] }, + { + "label": "Session", + "items": [ + { + "label": "publish", + "path": "reference/client-api/session/publish.md" + }, + { + "label": "publish_table", + "path": "reference/client-api/session/publish-table.md" + }, + { + "label": "fetch", + "path": "reference/client-api/session/fetch.md" + }, + { + "label": "fetch_table", + "path": "reference/client-api/session/fetch-table.md" + } + ] + }, { "label": "CSV", "items": [