frontend/instance/
log_handler.rs1use std::sync::Arc;
16
17use api::v1::RowInsertRequests;
18use async_trait::async_trait;
19use auth::{
20 LOG_WRITE, PIPELINE_DELETE, PIPELINE_INSERT, PIPELINE_QUERY, PermissionChecker,
21 PermissionCheckerRef, PermissionReq,
22};
23use client::Output;
24use common_error::ext::BoxedError;
25use datatypes::timestamp::TimestampNanosecond;
26use pipeline::{Pipeline, PipelineInfo, PipelineVersion};
27use servers::error::{
28 AuthSnafu, Error as ServerError, ExecuteGrpcRequestSnafu, PipelineSnafu, Result as ServerResult,
29};
30use servers::interceptor::{LogIngestInterceptor, LogIngestInterceptorRef};
31use servers::query_handler::PipelineHandler;
32use session::context::{QueryContext, QueryContextRef};
33use snafu::ResultExt;
34use table::Table;
35
36use crate::instance::Instance;
37
38impl Instance {
39 async fn prepare_log_insert(
40 &self,
41 log: RowInsertRequests,
42 ctx: QueryContextRef,
43 ) -> ServerResult<RowInsertRequests> {
44 self.plugins
45 .get::<PermissionCheckerRef>()
46 .as_ref()
47 .check_permission(ctx.current_user(), PermissionReq::Action(LOG_WRITE))
48 .context(AuthSnafu)?;
49
50 let log = self
51 .plugins
52 .get::<LogIngestInterceptorRef<ServerError>>()
53 .as_ref()
54 .pre_ingest(log, ctx.clone())?;
55
56 self.check_row_insert_permission(&log, &ctx, PermissionReq::Action(LOG_WRITE))
57 .context(AuthSnafu)?;
58
59 Ok(log)
60 }
61}
62
63#[async_trait]
64impl PipelineHandler for Instance {
65 async fn insert(&self, log: RowInsertRequests, ctx: QueryContextRef) -> ServerResult<Output> {
66 let log = self.prepare_log_insert(log, ctx.clone()).await?;
67 self.handle_log_inserts(log, Arc::new(ctx.fork())).await
68 }
69
70 async fn insert_all(
71 &self,
72 inputs: Vec<(QueryContextRef, RowInsertRequests)>,
73 ) -> ServerResult<Vec<ServerResult<Output>>> {
74 let mut prepared = Vec::with_capacity(inputs.len());
75 for (ctx, log) in inputs {
76 let log = self.prepare_log_insert(log, ctx.clone()).await?;
77 prepared.push((Arc::new(ctx.fork()), log));
80 }
81
82 operator::insert::admit_row_insert_batches(&mut prepared)
83 .await
84 .map_err(BoxedError::new)
85 .context(servers::error::ExecuteGrpcQuerySnafu)?;
86
87 let mut outputs = Vec::with_capacity(prepared.len());
88 for (ctx, log) in prepared {
89 outputs.push(self.handle_log_inserts(log, ctx).await);
90 }
91 Ok(outputs)
92 }
93
94 fn check_pipeline_query_permission(&self, query_ctx: &QueryContextRef) -> ServerResult<()> {
95 self.check_permission(query_ctx, PermissionReq::Action(PIPELINE_QUERY))
96 }
97
98 async fn get_pipeline(
99 &self,
100 name: &str,
101 version: PipelineVersion,
102 query_ctx: QueryContextRef,
103 ) -> ServerResult<Arc<Pipeline>> {
104 self.pipeline_operator
105 .get_pipeline(query_ctx, name, version)
106 .await
107 .context(PipelineSnafu)
108 }
109
110 async fn insert_pipeline(
111 &self,
112 name: &str,
113 content_type: &str,
114 pipeline: &str,
115 query_ctx: QueryContextRef,
116 ) -> ServerResult<PipelineInfo> {
117 self.check_permission(&query_ctx, PermissionReq::Action(PIPELINE_INSERT))?;
118 self.pipeline_operator
119 .insert_pipeline(name, content_type, pipeline, query_ctx)
120 .await
121 .context(PipelineSnafu)
122 }
123
124 async fn delete_pipeline(
125 &self,
126 name: &str,
127 version: PipelineVersion,
128 ctx: QueryContextRef,
129 ) -> ServerResult<Option<()>> {
130 self.check_permission(&ctx, PermissionReq::Action(PIPELINE_DELETE))?;
131 self.pipeline_operator
132 .delete_pipeline(name, version, ctx)
133 .await
134 .context(PipelineSnafu)
135 }
136
137 async fn get_table(
138 &self,
139 table: &str,
140 query_ctx: &QueryContext,
141 ) -> std::result::Result<Option<Arc<Table>>, catalog::error::Error> {
142 let catalog = query_ctx.current_catalog();
143 let schema = query_ctx.current_schema();
144 self.catalog_manager
145 .table(catalog, &schema, table, None)
146 .await
147 }
148
149 fn build_pipeline(&self, pipeline: &str) -> ServerResult<Pipeline> {
150 self.pipeline_operator
151 .build_pipeline(pipeline)
152 .context(PipelineSnafu)
153 }
154
155 async fn get_pipeline_str(
156 &self,
157 name: &str,
158 version: PipelineVersion,
159 query_ctx: QueryContextRef,
160 ) -> ServerResult<(String, TimestampNanosecond)> {
161 self.check_permission(&query_ctx, PermissionReq::Action(PIPELINE_QUERY))?;
162 self.pipeline_operator
163 .get_pipeline_str(name, version, query_ctx)
164 .await
165 .context(PipelineSnafu)
166 }
167}
168
169impl Instance {
170 pub async fn handle_log_inserts(
171 &self,
172 log: RowInsertRequests,
173 ctx: QueryContextRef,
174 ) -> ServerResult<Output> {
175 self.inserter
176 .handle_log_inserts(log, ctx, self.statement_executor.as_ref())
177 .await
178 .map_err(BoxedError::new)
179 .context(ExecuteGrpcRequestSnafu)
180 }
181
182 pub async fn handle_trace_inserts(
183 &self,
184 rows: RowInsertRequests,
185 ctx: QueryContextRef,
186 ) -> ServerResult<Output> {
187 self.inserter
188 .handle_trace_inserts(rows, ctx, self.statement_executor.as_ref())
189 .await
190 .map_err(BoxedError::new)
191 .context(ExecuteGrpcRequestSnafu)
192 }
193}