Skip to main content

headless_lms_chatbot/
azure_datasources.rs

1use secrecy::ExposeSecret;
2use serde_json::json;
3
4use crate::{
5    llm_utils::{azure_configuration, azure_search_configuration, azure_search_request},
6    prelude::*,
7};
8
9pub const API_VERSION: &str = "2024-07-01";
10
11pub async fn does_azure_datasource_exist(
12    datasource_name: &str,
13    app_config: &ApplicationConfiguration,
14) -> ChatbotResult<bool> {
15    let search_config = azure_search_configuration(app_config)?;
16    let mut url = search_config.search_endpoint.clone();
17    url.set_path(&format!("datasources('{}')", datasource_name));
18    url.set_query(Some(&format!("api-version={}", API_VERSION)));
19
20    let response = azure_search_request(reqwest::Method::GET, url, search_config)
21        .send()
22        .await?;
23
24    if response.status().is_success() {
25        Ok(true)
26    } else if response.status() == 404 {
27        Ok(false)
28    } else {
29        let status = response.status();
30        let error_text = response.text().await?;
31        Err(chatbot_err!(
32            FailedAzureResponse,
33            format!(
34                "Error checking if index exists. Status: {}. Error: {}",
35                status, error_text
36            )
37        ))
38    }
39}
40
41pub async fn create_azure_datasource(
42    datasource_name: &str,
43    container_name: &str,
44    app_config: &ApplicationConfiguration,
45) -> ChatbotResult<()> {
46    let azure_config = azure_configuration(app_config)?;
47
48    let search_config = azure_config.search_config.as_ref().ok_or_else(|| {
49        chatbot_err!(
50            AzureRequestBuildError,
51            "Azure search configuration is missing from the Azure configuration"
52        )
53    })?;
54
55    let blob_storage_config = azure_config.blob_storage_config.as_ref().ok_or_else(|| {
56        chatbot_err!(
57            AzureRequestBuildError,
58            "Blob storage configuration is missing from the Azure configuration"
59        )
60    })?;
61
62    let connection_string = blob_storage_config.connection_string()?;
63
64    let mut url = search_config.search_endpoint.clone();
65    url.set_path(&format!("datasources/{}", datasource_name));
66    url.set_query(Some(&format!("api-version={}", API_VERSION)));
67
68    let datasource_definition = json!({
69        "name": datasource_name,
70        "type": "azureblob",
71        "container": {
72            "name": container_name,
73        },
74        "credentials": {
75            "connectionString": connection_string.expose_secret(),
76        },
77        "dataDeletionDetectionPolicy": {
78            "@odata.type": "#Microsoft.Azure.Search.NativeBlobSoftDeleteDeletionDetectionPolicy",
79        }
80    });
81
82    let response = azure_search_request(reqwest::Method::PUT, url, search_config)
83        .json(&datasource_definition)
84        .send()
85        .await?;
86
87    if response.status().is_success() {
88        Ok(())
89    } else {
90        let status = response.status();
91        let error_text = response.text().await?;
92        Err(chatbot_err!(
93            FailedAzureResponse,
94            format!(
95                "Error creating datasource. Status: {}. Error: {}",
96                status, error_text
97            )
98        ))
99    }
100}