Skip to content

Commit

Permalink
Merge pull request #98 from oramasearch/feat/move-to-v1
Browse files Browse the repository at this point in the history
Move main APIs to v1
  • Loading branch information
allevo authored Jan 31, 2025
2 parents eb7eab3 + 1784910 commit c57dbe4
Show file tree
Hide file tree
Showing 11 changed files with 224 additions and 121 deletions.
13 changes: 8 additions & 5 deletions api-test.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ HTTP 200
[Captures]
collection_id: jsonpath "$[0]"

POST {{base_url}}/v0/collections
POST {{base_url}}/v1/collections/create
Authorization: Bearer my-master-api-key
{
"id": "{{collection_id}}",
Expand All @@ -18,12 +18,14 @@ Authorization: Bearer my-master-api-key
}
HTTP 201

GET {{base_url}}/v0/collections/{{collection_id}}
GET {{base_url}}/v1/collections/{{collection_id}}
Authorization: Bearer my-master-api-key
HTTP 200
[Asserts]
jsonpath "$.document_count" == 0

PATCH {{base_url}}/v0/collections/{{collection_id}}/documents

POST {{base_url}}/v1/collections/{{collection_id}}/insert
Authorization: Bearer my-write-api-key
[
{
Expand All @@ -41,12 +43,13 @@ Authorization: Bearer my-write-api-key
]
HTTP 200

GET {{base_url}}/v0/collections/{{collection_id}}
GET {{base_url}}/v1/collections/{{collection_id}}
Authorization: Bearer my-master-api-key
HTTP 200
[Asserts]
jsonpath "$.document_count" == 2

POST {{base_url}}/v0/collections/{{collection_id}}/search?api-key=my-read-api-key
POST {{base_url}}/v1/collections/{{collection_id}}/search?api-key=my-read-api-key
[Options]
retry: 10
retry-interval: 500ms
Expand Down
6 changes: 3 additions & 3 deletions embedding-api-test.hurl
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ HTTP 200
[Captures]
collection_id: jsonpath "$[0]"

POST {{base_url}}/v0/collections
POST {{base_url}}/v1/collections/create
Authorization: Bearer my-master-api-key
{
"id": "{{collection_id}}",
Expand All @@ -22,7 +22,7 @@ Authorization: Bearer my-master-api-key
}
HTTP 201

PATCH {{base_url}}/v0/collections/{{collection_id}}/documents
POST {{base_url}}/v1/collections/{{collection_id}}/insert
Authorization: Bearer my-write-api-key
[
{
Expand All @@ -41,7 +41,7 @@ Authorization: Bearer my-write-api-key
HTTP 200


POST {{base_url}}/v0/collections/{{collection_id}}/search?api-key=my-read-api-key
POST {{base_url}}/v1/collections/{{collection_id}}/search?api-key=my-read-api-key
Authorization: Bearer my-read-api-key
[Options]
retry: 10
Expand Down
2 changes: 1 addition & 1 deletion src/ai_server/src/actions/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ def __init__(self, config: OramaAIConfig):

def call_oramacore_search(self, collection_id: str, query: Dict) -> any:
body = json.dumps(query)
url = f"http://{self.config.rust_server_host}:{self.config.rust_server_port}/v0/{collection_id}/actions/execute"
url = f"http://{self.config.rust_server_host}:{self.config.rust_server_port}/v1/{collection_id}/actions/execute"

headers = {"Content-Type": "application/json; charset=utf-8"}
resp = requests.post(url=url, json={"context": body, "name": "search"}, headers=headers)
Expand Down
5 changes: 1 addition & 4 deletions src/collection_manager/dto.rs
Original file line number Diff line number Diff line change
Expand Up @@ -128,10 +128,7 @@ impl TryFrom<serde_json::Value> for CreateCollection {
}
}

#[derive(Debug, Serialize, Deserialize, ToSchema)]
pub struct DeleteDocuments {
pub document_ids: Vec<String>,
}
pub type DeleteDocuments = Vec<String>;

#[derive(Debug, Serialize, Deserialize, ToSchema, PartialEq, Eq)]
pub struct CollectionDTO {
Expand Down
92 changes: 70 additions & 22 deletions src/collection_manager/sides/write/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ use std::{

use super::hooks::{HookName, HooksRuntime};

use anyhow::{Context, Result};
use anyhow::{bail, Context, Result};
use duration_str::deserialize_duration;
use serde::{Deserialize, Serialize};
use tokio::{sync::RwLock, time::MissedTickBehavior};
Expand Down Expand Up @@ -208,9 +208,7 @@ impl WriteSide {
master_api_key: ApiKey,
option: CreateCollection,
) -> Result<()> {
if self.master_api_key != master_api_key {
return Err(anyhow::anyhow!("Invalid master api key"));
}
self.check_master_api_key(master_api_key)?;

self.collections
.create_collection(option, self.sender.clone(), self.hook_runtime.clone())
Expand Down Expand Up @@ -315,7 +313,7 @@ impl WriteSide {
&self,
write_api_key: ApiKey,
collection_id: CollectionId,
delete_documents: DeleteDocuments,
document_ids_to_delete: DeleteDocuments,
) -> Result<()> {
let collection = self
.collections
Expand All @@ -326,14 +324,15 @@ impl WriteSide {
collection.check_write_api_key(write_api_key)?;

collection
.delete_documents(delete_documents.document_ids, self.sender.clone())
.delete_documents(document_ids_to_delete, self.sender.clone())
.await?;

Ok(())
}

pub async fn insert_javascript_hook(
&self,
write_api_key: ApiKey,
collection_id: CollectionId,
name: HookName,
code: String,
Expand All @@ -348,6 +347,8 @@ impl WriteSide {
.await
.ok_or_else(|| anyhow::anyhow!("Collection not found"))?;

collection.check_write_api_key(write_api_key)?;

collection
.set_embedding_hook(name)
.await
Expand All @@ -356,39 +357,86 @@ impl WriteSide {
Ok(())
}

pub async fn list_collections(&self) -> Vec<CollectionDTO> {
self.collections.list().await
pub async fn list_collections(&self, master_api_key: ApiKey) -> Result<Vec<CollectionDTO>> {
self.check_master_api_key(master_api_key)?;

Ok(self.collections.list().await)
}

pub async fn get_collection_dto(&self, collection_id: CollectionId) -> Option<CollectionDTO> {
let collection = self.collections.get_collection(collection_id).await?;
Some(collection.as_dto().await)
pub async fn get_collection_dto(
&self,
master_api_key: ApiKey,
collection_id: CollectionId,
) -> Result<Option<CollectionDTO>> {
self.check_master_api_key(master_api_key)?;
let collection = match self.collections.get_collection(collection_id).await {
Some(collection) => collection,
None => return Ok(None),
};
Ok(Some(collection.as_dto().await))
}

pub fn get_javascript_hook(
pub async fn get_javascript_hook(
&self,
write_api_key: ApiKey,
collection_id: CollectionId,
name: HookName,
) -> Option<String> {
self.hook_runtime
) -> Result<Option<String>> {
let collection = self
.collections
.get_collection(collection_id.clone())
.await
.ok_or_else(|| anyhow::anyhow!("Collection not found"))?;
collection.check_write_api_key(write_api_key)?;

Ok(self
.hook_runtime
.get_hook(collection_id, name)
.map(|hook| hook.code)
.map(|hook| hook.code))
}

pub fn delete_javascript_hook(
pub async fn delete_javascript_hook(
&self,
_collection_id: CollectionId,
write_api_key: ApiKey,
collection_id: CollectionId,
_name: HookName,
) -> Option<String> {
None // @todo: implement delete hook in HooksRuntime and CollectionsWriter
) -> Result<Option<String>> {
let collection = self
.collections
.get_collection(collection_id)
.await
.ok_or_else(|| anyhow::anyhow!("Collection not found"))?;
collection.check_write_api_key(write_api_key)?;

bail!("Not implemented yet.") // @todo: implement delete hook in HooksRuntime and CollectionsWriter
}

pub fn list_javascript_hooks(&self, collection_id: CollectionId) -> HashMap<HookName, String> {
self.hook_runtime
pub async fn list_javascript_hooks(
&self,
write_api_key: ApiKey,
collection_id: CollectionId,
) -> Result<HashMap<HookName, String>> {
let collection = self
.collections
.get_collection(collection_id.clone())
.await
.ok_or_else(|| anyhow::anyhow!("Collection not found"))?;
collection.check_write_api_key(write_api_key)?;

Ok(self
.hook_runtime
.list_hooks(collection_id)
.into_iter()
.map(|(name, hook)| (name, hook.code))
.collect()
.collect())
}

fn check_master_api_key(&self, master_api_key: ApiKey) -> Result<()> {
if self.master_api_key != master_api_key {
return Err(anyhow::anyhow!("Invalid master api key"));
}

Ok(())
}
}

Expand Down
30 changes: 16 additions & 14 deletions src/tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ use crate::{
ai::AIServiceConfig,
build_orama,
collection_manager::{
dto::{ApiKey, DeleteDocuments},
dto::ApiKey,
sides::{
CollectionsWriterConfig, IndexesConfig, OramaModelSerializable, ReadSide, WriteSide,
},
Expand Down Expand Up @@ -263,7 +263,9 @@ async fn test_commit_and_load() -> Result<()> {
)
.await?;

let before_commit_collection_lists = write_side.list_collections().await;
let before_commit_collection_lists = write_side
.list_collections(ApiKey(Secret::new("my-master-api-key".to_string())))
.await?;

write_side.commit().await?;
read_side.commit().await?;
Expand All @@ -289,7 +291,9 @@ async fn test_commit_and_load() -> Result<()> {
after_commit_result.hits[0].id
);

let after_commit_collection_lists = write_side.list_collections().await;
let after_commit_collection_lists = write_side
.list_collections(ApiKey(Secret::new("my-master-api-key".to_string())))
.await?;

assert_eq!(
before_commit_collection_lists,
Expand All @@ -311,7 +315,9 @@ async fn test_commit_and_load() -> Result<()> {

assert_eq!(after_commit_result, after_load_result);

let after_load_collection_lists = write_side.list_collections().await;
let after_load_collection_lists = write_side
.list_collections(ApiKey(Secret::new("my-master-api-key".to_string())))
.await?;

assert_eq!(after_commit_collection_lists, after_load_collection_lists);

Expand Down Expand Up @@ -356,7 +362,9 @@ async fn test_get_collections() -> Result<()> {
create_collection(write_side.clone(), CollectionId(id.clone())).await?;
}

let collections = write_side.list_collections().await;
let collections = write_side
.list_collections(ApiKey(Secret::new("my-master-api-key".to_string())))
.await?;

assert_eq!(collections.len(), 3);

Expand Down Expand Up @@ -1496,9 +1504,7 @@ async fn test_delete_documents() -> Result<()> {
.delete_documents(
ApiKey(Secret::new("my-write-api-key".to_string())),
collection_id.clone(),
DeleteDocuments {
document_ids: vec![(document_count - 1).to_string()],
},
vec![(document_count - 1).to_string()],
)
.await?;
sleep(Duration::from_millis(100)).await;
Expand Down Expand Up @@ -1532,9 +1538,7 @@ async fn test_delete_documents() -> Result<()> {
.delete_documents(
ApiKey(Secret::new("my-write-api-key".to_string())),
collection_id.clone(),
DeleteDocuments {
document_ids: vec![(document_count - 2).to_string()],
},
vec![(document_count - 2).to_string()],
)
.await?;
sleep(Duration::from_millis(100)).await;
Expand Down Expand Up @@ -1568,9 +1572,7 @@ async fn test_delete_documents() -> Result<()> {
.delete_documents(
ApiKey(Secret::new("my-write-api-key".to_string())),
collection_id.clone(),
DeleteDocuments {
document_ids: vec![(document_count - 2).to_string()],
},
vec![(document_count - 2).to_string()],
)
.await?;
sleep(Duration::from_millis(500)).await;
Expand Down
2 changes: 1 addition & 1 deletion src/web_server/api/collection/actions.rs
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ struct ActionQueryParams {

#[endpoint(
method = "POST",
path = "/v0/{collection_id}/actions/execute",
path = "/v1/{collection_id}/actions/execute",
description = "Execute an action. Typically used by the Python server to perform actions that requires access to OramaCore components."
)]
#[axum::debug_handler]
Expand Down
Loading

0 comments on commit c57dbe4

Please sign in to comment.