Skip to main content

livekit_api/services/
databases.rs

1// Copyright 2026 LiveKit, Inc.
2//
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//     http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15use std::time::Duration;
16
17use livekit_protocol::agent_db;
18use livekit_token::get_env_keys;
19
20use super::{ServiceBase, ServiceResult};
21use crate::public_api::{self as api, call, next_cursor, opt, page_size, types, PROJECT};
22
23/// Agent databases of the project.
24#[derive(Debug)]
25pub struct DatabaseClient {
26    client: api::Client,
27}
28
29impl DatabaseClient {
30    /// Authenticates with an API key and secret, signing a short-lived token per request.
31    pub fn with_api_key(host: &str, api_key: &str, api_secret: &str) -> Self {
32        Self::build(
33            host,
34            ServiceBase::with_api_key(api_key, api_secret),
35            crate::http_client::client(),
36        )
37    }
38
39    /// Authenticates with a pre-signed token, sent verbatim on every request.
40    pub fn with_token(host: &str, token: &str) -> Self {
41        Self::build(host, ServiceBase::with_token(token), crate::http_client::client())
42    }
43
44    /// Reads the API key and secret from the `LIVEKIT_API_KEY` and
45    /// `LIVEKIT_API_SECRET` environment variables.
46    pub fn new(host: &str) -> ServiceResult<Self> {
47        let (api_key, api_secret) = get_env_keys()?;
48        Ok(Self::with_api_key(host, &api_key, &api_secret))
49    }
50
51    /// Builds the client from an already-constructed HTTP client so the unified
52    /// [`LiveKitApi`](super::LiveKitApi) can share one connection pool across services.
53    pub(crate) fn build(host: &str, base: ServiceBase, http: crate::http_client::Client) -> Self {
54        Self { client: api::client(host, base, http) }
55    }
56
57    /// Overrides the default per-request timeout (10s) for calls on this client.
58    pub fn with_request_timeout(mut self, timeout: Duration) -> Self {
59        self.client.inner.timeout = timeout;
60        self
61    }
62
63    pub async fn create(
64        &self,
65        req: agent_db::CreateRequest,
66    ) -> ServiceResult<agent_db::CreateResponse> {
67        let body = types::DatabaseServiceCreateDatabaseBody { ttl: req.ttl };
68        let res = call(self.client.database_service_create_database(PROJECT, &body)).await?;
69        Ok(agent_db::CreateResponse {
70            database_id: res.database_id.unwrap_or_default(),
71            expires_at: res.expires_at,
72        })
73    }
74
75    pub async fn get(&self, database_id: &str) -> ServiceResult<agent_db::AgentDatabase> {
76        let res = call(self.client.database_service_get_database(PROJECT, database_id)).await?;
77        Ok(res.database.unwrap_or_default())
78    }
79
80    pub async fn list(&self, req: agent_db::ListRequest) -> ServiceResult<agent_db::ListResponse> {
81        let res = call(self.client.database_service_list_databases(
82            PROJECT,
83            opt(&req.page_token),
84            page_size(req.page_size),
85        ))
86        .await?;
87        Ok(agent_db::ListResponse {
88            databases: res.items,
89            next_page_token: next_cursor(res.page_info),
90        })
91    }
92
93    pub async fn delete(&self, database_id: &str) -> ServiceResult<()> {
94        call(self.client.database_service_delete_database(PROJECT, database_id)).await?;
95        Ok(())
96    }
97
98    /// A pre-authenticated download URL of a consistent snapshot of the database.
99    pub async fn export(&self, database_id: &str) -> ServiceResult<agent_db::ExportResponse> {
100        let res = call(self.client.database_service_export_database(PROJECT, database_id)).await?;
101        Ok(agent_db::ExportResponse {
102            download_url: res.download_url.unwrap_or_default(),
103            expires_at: res.expires_at,
104            tip: res.tip.and_then(|t| t.parse().ok()).unwrap_or_default(),
105        })
106    }
107}