Skip to content

Commit

Permalink
refactor(webserver): extract RepositoryService (#1897)
Browse files Browse the repository at this point in the history
* refactor(webserver): extract RepositoryService

* add unit test

* update

* update naming

* [autofix.ci] apply automated fixes

---------

Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
  • Loading branch information
wsxiaoys and autofix-ci[bot] authored Apr 20, 2024
1 parent a3d7a75 commit 0814898
Show file tree
Hide file tree
Showing 8 changed files with 175 additions and 120 deletions.
76 changes: 16 additions & 60 deletions ee/tabby-webserver/src/handler.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
use std::sync::Arc;

use async_trait::async_trait;
use axum::{
extract::{Path, State},
http::Request,
Expand All @@ -17,7 +16,7 @@ use tabby_common::{
event::{ComposedLogger, EventLogger},
server_setting::ServerSetting,
},
config::{RepositoryAccess, RepositoryConfig},
config::RepositoryAccess,
};
use tabby_db::DbConn;
use tracing::{error, warn};
Expand All @@ -30,73 +29,33 @@ use crate::{
path::db_file,
repositories,
schema::{
auth::AuthenticationService, create_schema, git_repository::GitRepositoryService,
github_repository_provider::GithubRepositoryProviderService, Schema, ServiceLocator,
},
service::{
create_service_locator, event_logger::create_event_logger,
new_github_repository_provider_service,
auth::AuthenticationService, create_schema, repository::RepositoryService, Schema,
ServiceLocator,
},
service::{create_service_locator, event_logger::create_event_logger, repository},
ui,
};

struct RepositoryAccessImpl {
git_repository_service: Arc<dyn GitRepositoryService>,
github_repository_service: Arc<dyn GithubRepositoryProviderService>,
}

#[async_trait]
impl RepositoryAccess for RepositoryAccessImpl {
async fn list_repositories(&self) -> anyhow::Result<Vec<RepositoryConfig>> {
let mut repos: Vec<RepositoryConfig> = self
.git_repository_service
.list(None, None, None, None)
.await?
.into_iter()
.map(|repo| RepositoryConfig::new(repo.git_url))
.collect();

repos.extend(
self.github_repository_service
.list_provided_git_urls()
.await
.unwrap_or_default()
.into_iter()
.map(RepositoryConfig::new),
);

Ok(repos)
}
}

pub struct WebserverHandle {
db: DbConn,
logger: Arc<dyn EventLogger>,
git_repository_service: Arc<dyn GitRepositoryService>,
github_repository_service: Arc<dyn GithubRepositoryProviderService>,
repository_access: Arc<dyn RepositoryAccess>,
repository: Arc<dyn RepositoryService>,
}

impl WebserverHandle {
pub async fn new(logger1: impl EventLogger + 'static) -> Self {
let db = DbConn::new(db_file().as_path())
.await
.expect("Must be able to initialize db");
let git_repository_service = Arc::new(db.clone());
let github_repository_service =
Arc::new(new_github_repository_provider_service(db.clone()));

let repository = repository::create(db.clone());

let logger2 = create_event_logger(db.clone());
let logger = Arc::new(ComposedLogger::new(logger1, logger2));
WebserverHandle {
db,
logger,
git_repository_service: git_repository_service.clone(),
github_repository_service: github_repository_service.clone(),
repository_access: Arc::new(RepositoryAccessImpl {
git_repository_service,
github_repository_service,
}),
repository,
}
}

Expand All @@ -105,7 +64,7 @@ impl WebserverHandle {
}

pub fn repository_access(&self) -> Arc<dyn RepositoryAccess> {
self.repository_access.clone()
self.repository.clone().access()
}

pub async fn attach_webserver(
Expand All @@ -119,8 +78,7 @@ impl WebserverHandle {
let ctx = create_service_locator(
self.logger(),
code,
self.git_repository_service.clone(),
self.github_repository_service.clone(),
self.repository.clone(),
self.db.clone(),
is_chat_enabled,
)
Expand All @@ -147,20 +105,18 @@ impl WebserverHandle {
.layer(Extension(schema))
.route(
"/hub",
routing::get(hub::ws_handler)
.with_state(HubState::new(ctx.clone(), self.repository_access.clone()).into()),
routing::get(hub::ws_handler).with_state(
HubState::new(ctx.clone(), self.repository_access().clone()).into(),
),
)
.nest(
"/repositories",
repositories::routes(ctx.repository(), ctx.auth()),
// FIXME(boxbeam): repositories routes should support both git / github repositories, but currently only git repositories are supported.
repositories::routes(ctx.repository().git(), ctx.auth()),
)
.nest(
"/integrations/github",
integrations::github::routes(
ctx.auth(),
ctx.setting(),
ctx.github_repository_provider(),
),
integrations::github::routes(ctx.auth(), ctx.setting(), ctx.repository().github()),
)
.route(
"/avatar/:id",
Expand Down
23 changes: 2 additions & 21 deletions ee/tabby-webserver/src/schema/git_repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,11 +4,11 @@ use lazy_static::lazy_static;
use regex::Regex;
use validator::Validate;

use super::{Context, Result};
use super::{repository::FileEntrySearchResult, Context, Result};
use crate::juniper::relay::NodeType;

lazy_static! {
static ref REPOSITORY_NAME_REGEX: Regex = Regex::new("").unwrap();
static ref REPOSITORY_NAME_REGEX: Regex = Regex::new("^[a-zA-Z][\\w.-]+$").unwrap();
}

#[derive(Validate)]
Expand All @@ -31,25 +31,6 @@ pub struct GitRepository {
pub git_url: String,
}

#[derive(GraphQLObject, Debug)]
pub struct FileEntrySearchResult {
pub r#type: String,
pub path: String,

/// matched indices for fuzzy search query.
pub indices: Vec<i32>,
}

impl FileEntrySearchResult {
pub fn new(r#type: String, path: String, indices: Vec<u32>) -> Self {
Self {
r#type,
path,
indices: indices.into_iter().map(|i| i as i32).collect(),
}
}
}

impl NodeType for GitRepository {
type Cursor = String;

Expand Down
36 changes: 25 additions & 11 deletions ee/tabby-webserver/src/schema/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pub mod git_repository;
pub mod github_repository_provider;
pub mod job;
pub mod license;
pub mod repository;
pub mod setting;
pub mod worker;

Expand Down Expand Up @@ -40,14 +41,15 @@ use self::{
},
job::JobStats,
license::{IsLicenseValid, LicenseInfo, LicenseService, LicenseType},
repository::RepositoryService,
setting::{
NetworkSetting, NetworkSettingInput, SecuritySetting, SecuritySettingInput, SettingService,
},
};
use crate::{
axum::FromAuth,
juniper::relay::{self, Connection},
schema::git_repository::FileEntrySearchResult,
schema::repository::FileEntrySearchResult,
};

pub trait ServiceLocator: Send + Sync {
Expand All @@ -56,12 +58,11 @@ pub trait ServiceLocator: Send + Sync {
fn code(&self) -> Arc<dyn CodeSearch>;
fn logger(&self) -> Arc<dyn EventLogger>;
fn job(&self) -> Arc<dyn JobService>;
fn repository(&self) -> Arc<dyn GitRepositoryService>;
fn repository(&self) -> Arc<dyn RepositoryService>;
fn email(&self) -> Arc<dyn EmailService>;
fn setting(&self) -> Arc<dyn SettingService>;
fn license(&self) -> Arc<dyn LicenseService>;
fn analytic(&self) -> Arc<dyn AnalyticService>;
fn github_repository_provider(&self) -> Arc<dyn GithubRepositoryProviderService>;
}

pub struct Context {
Expand Down Expand Up @@ -234,7 +235,8 @@ impl Query {
last,
|after, before, first, last| async move {
ctx.locator
.github_repository_provider()
.repository()
.github()
.list_github_repository_providers(
ids.unwrap_or_default(),
after,
Expand Down Expand Up @@ -264,7 +266,8 @@ impl Query {
last,
|after, before, first, last| async move {
ctx.locator
.github_repository_provider()
.repository()
.github()
.list_github_provided_repositories_by_provider(
provider_ids,
after,
Expand Down Expand Up @@ -339,6 +342,7 @@ impl Query {
|after, before, first, last| async move {
ctx.locator
.repository()
.git()
.list(after, before, first, last)
.await
},
Expand All @@ -354,6 +358,7 @@ impl Query {
check_claims(ctx)?;
ctx.locator
.repository()
.git()
.search_files(&repository_name, &pattern, 40)
.await
}
Expand Down Expand Up @@ -594,13 +599,14 @@ impl Mutation {
input.validate()?;
ctx.locator
.repository()
.git()
.create(input.name, input.git_url)
.await
}

async fn delete_git_repository(ctx: &Context, id: ID) -> Result<bool> {
check_admin(ctx).await?;
ctx.locator.repository().delete(&id).await
ctx.locator.repository().git().delete(&id).await
}

async fn update_git_repository(
Expand All @@ -610,7 +616,11 @@ impl Mutation {
git_url: String,
) -> Result<bool> {
check_admin(ctx).await?;
ctx.locator.repository().update(&id, name, git_url).await
ctx.locator
.repository()
.git()
.update(&id, name, git_url)
.await
}

async fn delete_invitation(ctx: &Context, id: ID) -> Result<ID> {
Expand Down Expand Up @@ -682,7 +692,8 @@ impl Mutation {
check_admin(ctx).await?;
input.validate()?;
ctx.locator
.github_repository_provider()
.repository()
.github()
.create_github_repository_provider(
input.display_name,
input.application_id,
Expand All @@ -695,7 +706,8 @@ impl Mutation {
async fn delete_github_repository_provider(ctx: &Context, id: ID) -> Result<bool> {
check_admin(ctx).await?;
ctx.locator
.github_repository_provider()
.repository()
.github()
.delete_github_repository_provider(id)
.await?;
Ok(true)
Expand All @@ -708,7 +720,8 @@ impl Mutation {
check_admin(ctx).await?;
input.validate()?;
ctx.locator
.github_repository_provider()
.repository()
.github()
.update_github_repository_provider(
input.id,
input.display_name,
Expand All @@ -725,7 +738,8 @@ impl Mutation {
active: bool,
) -> Result<bool> {
ctx.locator
.github_repository_provider()
.repository()
.github()
.update_github_provided_repository_active(id, active)
.await?;
Ok(true)
Expand Down
36 changes: 36 additions & 0 deletions ee/tabby-webserver/src/schema/repository.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
use std::sync::Arc;

use async_trait::async_trait;
use juniper::GraphQLObject;
use tabby_common::config::RepositoryAccess;

use super::{
git_repository::GitRepositoryService,
github_repository_provider::GithubRepositoryProviderService,
};

#[derive(GraphQLObject, Debug)]
pub struct FileEntrySearchResult {
pub r#type: String,
pub path: String,

/// matched indices for fuzzy search query.
pub indices: Vec<i32>,
}

impl FileEntrySearchResult {
pub fn new(r#type: String, path: String, indices: Vec<u32>) -> Self {
Self {
r#type,
path,
indices: indices.into_iter().map(|i| i as i32).collect(),
}
}
}

#[async_trait]
pub trait RepositoryService: Send + Sync + RepositoryAccess {
fn git(&self) -> Arc<dyn GitRepositoryService>;
fn github(&self) -> Arc<dyn GithubRepositoryProviderService>;
fn access(self: Arc<Self>) -> Arc<dyn RepositoryAccess>;
}
3 changes: 2 additions & 1 deletion ee/tabby-webserver/src/service/git_repository.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ use tabby_db::DbConn;

use super::{graphql_pagination_to_filter, AsID, AsRowid};
use crate::schema::{
git_repository::{FileEntrySearchResult, GitRepository, GitRepositoryService},
git_repository::{GitRepository, GitRepositoryService},
repository::FileEntrySearchResult,
Result,
};

Expand Down
Loading

0 comments on commit 0814898

Please sign in to comment.