Remote App Serving
Remote App Serving in this SDK allows for the deployment and management of long-running applications within the Flyte ecosystem. Unlike standard tasks that run to completion, an App represents a persistent service with a public endpoint and a managed lifecycle.
The core implementation resides in the App class within src/flyte/remote/_app.py, which wraps the underlying app_definition_pb2.App protobuf and provides high-level methods for lifecycle control, status monitoring, and resource discovery.
App Lifecycle Management
The lifecycle of an app is governed by its desired_state, which can be transitioned between STARTED and STOPPED. The SDK provides explicit methods to manage these transitions, supporting both synchronous and asynchronous (via .aio) execution.
Activation and Deactivation
To start or stop an app, use the activate() and deactivate() methods. These methods update the app's specification on the control plane.
# From src/flyte/remote/_app.py
app = App.get(name="my-service")
# Start the app and wait for it to be ready
app.activate(wait=True)
# Stop the app
app.deactivate(wait=False)
When wait=True is passed, the SDK uses the watch() method to block until the app reaches the target state.
Ephemeral Contexts
For temporary deployments, the App class provides context managers that ensure an app is activated when entering the block and automatically deactivated upon exit. This is useful for integration tests or short-lived service requirements.
# Synchronous context manager
with app.ephemeral_ctx_sync():
print(f"App is live at: {app.endpoint}")
# Perform operations against the app endpoint
# Asynchronous context manager
async with app.ephemeral_ctx():
await perform_async_tasks(app.endpoint)
Monitoring and Status
The SDK tracks the state of an app through its deployment_status and desired_state properties.
State Transitions with Watch
The watch() method provides a gRPC-based stream to monitor an app's progress toward a desired state (activated or deactivated).
# Watch for an app to become active
try:
updated_app = app.watch(wait_for="activated")
print(f"App {updated_app.name} is now {updated_app.deployment_status}")
except RuntimeError as e:
# Raised if the deployment fails or stalls
print(f"Deployment failed: {e}")
Status Properties
You can inspect the current state of an app using several helper properties:
is_active(): ReturnsTrueif the deployment status indicates the app is started.is_deactivated(): ReturnsTrueif the app is stopped.endpoint: Returns the public URL (ingress) where the app is reachable.deployment_status: Returns the rawDeploymentStatusenum from the protobuf.
Deployment and Discovery
The SDK handles app creation and updates through a robust mechanism that manages existing resources.
Create and Replace Logic
The App.create() method attempts to deploy a new app. If the app already exists (indicated by an ALREADY_EXISTS error from the server), it automatically falls back to App.replace().
# Internal logic in App.create (src/flyte/remote/_app.py)
try:
resp = await get_client().app_service.create(...)
except ConnectError as e:
if e.code == Code.ALREADY_EXISTS:
# Automatically update the existing app
return await App.replace.aio(...)
App.replace() includes an optimization via _app_specs_are_equal(): if the new specification matches the existing one, the update is skipped to avoid unnecessary revision increments.
Resource Discovery
Apps can be retrieved or listed using class methods:
App.get(name, project, domain): Fetches a specific app by its identifier.App.listall(): Returns an async iterator over all apps, supporting filtering by creator and sorting.App.delete(name): Removes an app from the control plane.
Console Integration
The Console class in src/flyte/remote/_client/controlplane.py is responsible for generating human-readable URLs for Flyte resources. The App.url property leverages this to provide a direct link to the Flyte UI for a specific application.
# Example of how Console builds the URL
# src/flyte/remote/_client/controlplane.py
def app_url(self, project: str, domain: str, app_name: str) -> str:
return f"{self._http_domain}/v2/domain/{domain}/project/{project}/apps/{app_name}"
The Console class automatically normalizes the domain from the configured Flyte endpoint. Notably, it includes a hardcoded mapping for local development: if the endpoint is localhost:8090, the console URL is redirected to localhost:8080 where the Flyte dashboard typically resides.