-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Implements a mutation endpoint to run procedures. I added an example native query to fixtures, `insertArtist`, to demonstrate. I'll follow up with another PR that implements arguments to native queries where I'll replace the hard-coded inputs. I'm having a problem querying the `Artist` collection which I think is unrelated, but I'm going to check that out and likely submit a bug fix PR. I confirmed that `insertArtist` does update the database correctly, and I wanted to get this PR out. Ticket: https://hasurahq.atlassian.net/browse/MDB-86
- Loading branch information
Showing
9 changed files
with
189 additions
and
7 deletions.
There are no files selected for viewing
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,98 @@ | ||
use std::collections::BTreeMap; | ||
|
||
use configuration::native_queries::NativeQuery; | ||
use futures::future::try_join_all; | ||
use itertools::Itertools; | ||
use mongodb::Database; | ||
use mongodb_agent_common::interface_types::MongoConfig; | ||
use ndc_sdk::{ | ||
connector::MutationError, | ||
json_response::JsonResponse, | ||
models::{MutationOperation, MutationOperationResults, MutationRequest, MutationResponse}, | ||
}; | ||
use serde_json::Value; | ||
|
||
/// A procedure combined with inputs | ||
#[derive(Clone, Debug)] | ||
#[allow(dead_code)] | ||
struct Job<'a> { | ||
// For the time being all procedures are native queries. | ||
native_query: &'a NativeQuery, | ||
arguments: BTreeMap<String, Value>, | ||
} | ||
|
||
impl<'a> Job<'a> { | ||
pub fn new(native_query: &'a NativeQuery, arguments: BTreeMap<String, Value>) -> Self { | ||
Job { | ||
native_query, | ||
arguments, | ||
} | ||
} | ||
} | ||
|
||
pub async fn handle_mutation_request( | ||
config: &MongoConfig, | ||
mutation_request: MutationRequest, | ||
) -> Result<JsonResponse<MutationResponse>, MutationError> { | ||
tracing::debug!(?config, mutation_request = %serde_json::to_string(&mutation_request).unwrap(), "executing mutation"); | ||
let database = config.client.database(&config.database); | ||
let jobs = look_up_procedures(config, mutation_request)?; | ||
let operation_results = try_join_all( | ||
jobs.into_iter() | ||
.map(|job| execute_job(database.clone(), job)), | ||
) | ||
.await?; | ||
Ok(JsonResponse::Value(MutationResponse { operation_results })) | ||
} | ||
|
||
/// Looks up procedures according to the names given in the mutation request, and pairs them with | ||
/// arguments and requested fields. Returns an error if any procedures cannot be found. | ||
fn look_up_procedures( | ||
config: &MongoConfig, | ||
mutation_request: MutationRequest, | ||
) -> Result<Vec<Job<'_>>, MutationError> { | ||
let (jobs, not_found): (Vec<Job>, Vec<String>) = mutation_request | ||
.operations | ||
.into_iter() | ||
.map(|operation| match operation { | ||
MutationOperation::Procedure { | ||
name, arguments, .. | ||
} => { | ||
let native_query = config | ||
.native_queries | ||
.iter() | ||
.find(|native_query| native_query.name == name); | ||
native_query.ok_or(name).map(|nq| Job::new(nq, arguments)) | ||
} | ||
}) | ||
.partition_result(); | ||
|
||
if !not_found.is_empty() { | ||
return Err(MutationError::UnprocessableContent(format!( | ||
"request includes unknown procedures: {}", | ||
not_found.join(", ") | ||
))); | ||
} | ||
|
||
Ok(jobs) | ||
} | ||
|
||
async fn execute_job( | ||
database: Database, | ||
job: Job<'_>, | ||
) -> Result<MutationOperationResults, MutationError> { | ||
let result = database | ||
.run_command(job.native_query.command.clone(), None) | ||
.await | ||
.map_err(|err| match *err.kind { | ||
mongodb::error::ErrorKind::InvalidArgument { message, .. } => { | ||
MutationError::UnprocessableContent(message) | ||
} | ||
err => MutationError::Other(Box::new(err)), | ||
})?; | ||
let json_result = | ||
serde_json::to_value(result).map_err(|err| MutationError::Other(Box::new(err)))?; | ||
Ok(MutationOperationResults::Procedure { | ||
result: json_result, | ||
}) | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,4 +1,5 @@ | ||
name: hello | ||
description: Example of a read-only native query | ||
objectTypes: | ||
- name: HelloResult | ||
fields: | ||
|
16 changes: 16 additions & 0 deletions
16
fixtures/connector/chinook/native_queries/insert_artist.yaml
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,16 @@ | ||
name: insertArtist | ||
description: Example of a database update using a native query | ||
objectTypes: | ||
- name: InsertArtist | ||
fields: | ||
- name: ok | ||
type: !scalar int | ||
- name: n | ||
type: !scalar int | ||
resultType: !object InsertArtist | ||
# TODO: implement arguments instead of hard-coding inputs | ||
command: | ||
insert: "Artist" | ||
documents: | ||
- ArtistId: 1001 | ||
Name: Regina Spektor |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,54 @@ | ||
kind: Command | ||
version: v1 | ||
definition: | ||
name: insertArtist | ||
description: Example of a database update using a native query | ||
outputType: InsertArtist | ||
arguments: [] | ||
source: | ||
dataConnectorName: mongodb | ||
dataConnectorCommand: | ||
procedure: insertArtist | ||
typeMapping: | ||
InsertArtist: | ||
fieldMapping: | ||
ok: { column: ok } | ||
n: { column: n } | ||
graphql: | ||
rootFieldName: insertArtist | ||
rootFieldKind: Mutation | ||
|
||
--- | ||
kind: CommandPermissions | ||
version: v1 | ||
definition: | ||
commandName: insertArtist | ||
permissions: | ||
- role: admin | ||
allowExecution: true | ||
|
||
--- | ||
kind: ObjectType | ||
version: v1 | ||
definition: | ||
name: InsertArtist | ||
graphql: | ||
typeName: InsertArtist | ||
fields: | ||
- name: ok | ||
type: Int! | ||
- name: n | ||
type: Int! | ||
|
||
--- | ||
kind: TypePermissions | ||
version: v1 | ||
definition: | ||
typeName: InsertArtist | ||
permissions: | ||
- role: admin | ||
output: | ||
allowedFields: | ||
- ok | ||
- n | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters