Skip to main content

frontend/instance/
log_handler.rs

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