Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
30 changes: 30 additions & 0 deletions apps/docs/public/openapi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1053,6 +1053,19 @@ components:
items:
$ref: '#/components/schemas/Version'
description: Versions that the project depends upon
ProjectDependentsList:
type: object
properties:
projects:
type: array
items:
$ref: '#/components/schemas/Project'
description: Projects that that depend on the project
versions:
type: array
items:
$ref: '#/components/schemas/Version'
description: Versions that depend on the project
PatchProjectsBody:
type: object
properties:
Expand Down Expand Up @@ -2396,6 +2409,23 @@ paths:
$ref: '#/components/schemas/ProjectDependencyList'
'404':
description: The requested item(s) were not found or no authorization to access the requested item(s)
/project/{id|slug}/dependents:
parameters:
- $ref: '#/components/parameters/ProjectIdentifier'
get:
summary: Get all dependents for a project
operationId: getDependents
tags:
- projects
responses:
'200':
description: Expected response to a valid request
content:
application/json:
schema:
$ref: '#/components/schemas/ProjectDependentsList'
'404':
description: The requested item(s) were not found or no authorization to access the requested item(s)
/project/{id|slug}/follow:
parameters:
- $ref: '#/components/parameters/ProjectIdentifier'
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

68 changes: 66 additions & 2 deletions apps/labrinth/src/database/models/project_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ use std::hash::Hash;
pub const PROJECTS_NAMESPACE: &str = "projects";
pub const PROJECTS_SLUGS_NAMESPACE: &str = "projects_slugs";
const PROJECTS_DEPENDENCIES_NAMESPACE: &str = "projects_dependencies";
const PROJECTS_DEPENDENTS_NAMESPACE: &str = "projects_dependents";

#[derive(Clone, Debug, Serialize, Deserialize)]
pub struct LinkUrl {
Expand Down Expand Up @@ -351,8 +352,14 @@ impl DBProject {
let project = Self::get_id(id, &mut **transaction, redis).await?;

if let Some(project) = project {
DBProject::clear_cache(id, project.inner.slug, Some(true), redis)
.await?;
DBProject::clear_cache(
id,
project.inner.slug,
Some(true),
Some(true),
redis,
)
.await?;

sqlx::query!(
"
Expand Down Expand Up @@ -944,10 +951,59 @@ impl DBProject {
Ok(dependencies)
}

pub async fn get_dependents<'a, E>(
id: DBProjectId,
exec: E,
redis: &RedisPool,
) -> Result<Vec<(DBVersionId, DBProjectId)>, DatabaseError>
where
E: sqlx::Executor<'a, Database = sqlx::Postgres>,
{
type Dependents = Vec<(DBVersionId, DBProjectId)>;

let mut redis = redis.connect().await?;

let dependents = redis
.get_deserialized_from_json::<Dependents>(
PROJECTS_DEPENDENTS_NAMESPACE,
&id.0.to_string(),
)
.await?;
if let Some(dependents) = dependents {
return Ok(dependents);
}

let dependents: Dependents = sqlx::query!(
"
SELECT DISTINCT version.id version_id, mod.id FROM versions version
INNER JOIN mods mod ON version.mod_id = mod.id
INNER JOIN dependencies d ON version.id = d.dependent_id
WHERE mod.status = 'approved' AND d.mod_dependency_id = $1
ORDER BY mod.id;
",
id as DBProjectId
)
.fetch(exec)
.map_ok(|x| (DBVersionId(x.version_id), DBProjectId(x.id)))
.try_collect::<Dependents>()
.await?;

redis
.set_serialized_to_json(
PROJECTS_DEPENDENTS_NAMESPACE,
id.0,
&dependents,
None,
)
.await?;
Ok(dependents)
}

pub async fn clear_cache(
id: DBProjectId,
slug: Option<String>,
clear_dependencies: Option<bool>,
clear_dependents: Option<bool>,
redis: &RedisPool,
) -> Result<(), DatabaseError> {
let mut redis = redis.connect().await?;
Expand All @@ -964,6 +1020,14 @@ impl DBProject {
None
},
),
(
PROJECTS_DEPENDENTS_NAMESPACE,
if clear_dependents.unwrap_or(false) {
Some(id.0.to_string())
} else {
None
},
),
])
.await?;
Ok(())
Expand Down
1 change: 1 addition & 0 deletions apps/labrinth/src/database/models/version_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -449,6 +449,7 @@ impl DBVersion {
DBProjectId(project_id.mod_id),
None,
None,
None,
redis,
)
.await?;
Expand Down
1 change: 1 addition & 0 deletions apps/labrinth/src/queue/moderation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -702,6 +702,7 @@ impl AutomatedModerationQueue {
project.inner.id,
project.inner.slug.clone(),
None,
None,
&redis,
)
.await?;
Expand Down
49 changes: 48 additions & 1 deletion apps/labrinth/src/routes/v2/projects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,8 @@ pub fn config(cfg: &mut web::ServiceConfig) {
web::scope("{project_id}")
.service(super::versions::version_list)
.service(super::versions::version_project_get)
.service(dependency_list),
.service(dependency_list)
.service(dependents_list),
),
);
}
Expand Down Expand Up @@ -306,6 +307,52 @@ pub async fn dependency_list(
}
}

#[get("dependents")]
pub async fn dependents_list(
req: HttpRequest,
info: web::Path<(String,)>,
pool: web::Data<PgPool>,
redis: web::Data<RedisPool>,
session_queue: web::Data<AuthQueue>,
) -> Result<HttpResponse, ApiError> {
// TODO: tests, probably
let response = v3::projects::dependents_list(
req,
info,
pool.clone(),
redis.clone(),
session_queue,
)
.await
.or_else(v2_reroute::flatten_404_error)?;

match v2_reroute::extract_ok_json::<
crate::routes::v3::projects::DependencyInfo,
>(response)
.await
{
Ok(dependency_info) => {
let converted_projects = LegacyProject::from_many(
dependency_info.projects,
&**pool,
&redis,
)
.await?;
let converted_versions = dependency_info
.versions
.into_iter()
.map(LegacyVersion::from)
.collect();

Ok(HttpResponse::Ok().json(DependencyInfo {
projects: converted_projects,
versions: converted_versions,
}))
}
Err(response) => Ok(response),
}
}

#[derive(Serialize, Deserialize, Validate)]
pub struct EditProject {
#[validate(
Expand Down
2 changes: 2 additions & 0 deletions apps/labrinth/src/routes/v3/organizations.rs
Original file line number Diff line number Diff line change
Expand Up @@ -831,6 +831,7 @@ pub async fn organization_projects_add(
project_item.inner.id,
project_item.inner.slug,
None,
None,
&redis,
)
.await?;
Expand Down Expand Up @@ -1019,6 +1020,7 @@ pub async fn organization_projects_remove(
project_item.inner.id,
project_item.inner.slug,
None,
None,
&redis,
)
.await?;
Expand Down
Loading