Skip to content
This repository was archived by the owner on Jun 7, 2026. It is now read-only.

Commit ec46960

Browse files
committed
Avoid adding duplicate project issues internally
1 parent f63191f commit ec46960

17 files changed

Lines changed: 214 additions & 167 deletions

File tree

src/api/v1/authors/projects.cc

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@
1313
// ReSharper disable once CppUnusedIncludeDirective
1414
#include <service/serializers.h>
1515
#include <service/storage/gitops.h>
16+
#include <service/storage/issues/issue_service.h>
1617
#include <service/util.h>
1718
#include <version.h>
1819

@@ -387,11 +388,11 @@ namespace api::v1 {
387388
}
388389
resolvedPath = *filePath;
389390
}
390-
const auto res = co_await global::storage->addProjectIssue(resolved, parsedLevel, parsedType, parsedSubject, details, resolvedPath);
391-
if (res == Error::ErrNotFound) {
391+
const auto res = co_await global::issues->addProjectIssueExternal(resolved, parsedLevel, parsedType, parsedSubject, details, resolvedPath);
392+
if (res.error() == Error::ErrNotFound) {
392393
throw ApiException(Error::ErrNotFound, "not_found");
393394
}
394395

395-
callback(statusResponse(res == Error::Ok ? k201Created : k409Conflict));
396+
callback(statusResponse(res.error() == Error::Ok ? k201Created : k409Conflict));
396397
}
397398
}

src/main.cc

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <service/project/virtual/virtual.h>
2323
#include <service/storage/ingestor/recipe/recipe_builtin.h>
2424
#include <service/storage/realtime.h>
25+
#include <service/storage/issues/issue_service.h>
2526
#include <service/system/access_keys.h>
2627
#include <service/system/game_data.h>
2728
#include <service/system/lang.h>
@@ -42,6 +43,7 @@ namespace global {
4243
std::shared_ptr<GitHub> github;
4344
std::shared_ptr<realtime::ConnectionManager> connections;
4445
std::shared_ptr<Storage> storage;
46+
std::shared_ptr<IssueService> issues;
4547
std::shared_ptr<Auth> auth;
4648
std::shared_ptr<LangService> lang;
4749
std::shared_ptr<GameDataService> gameData;
@@ -100,6 +102,7 @@ int main() {
100102
global::github = std::make_shared<GitHub>();
101103
global::connections = std::make_shared<realtime::ConnectionManager>();
102104
global::storage = std::make_shared<Storage>(storagePath);
105+
global::issues = std::make_shared<IssueService>();
103106
global::auth = std::make_shared<Auth>(appUrl, OAuthApp{githubAppConfig.clientId, githubAppConfig.clientSecret},
104107
OAuthApp{mrApp.clientId, mrApp.clientSecret});
105108
global::lang = std::make_shared<LangService>();

src/service/CMakeLists.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,12 @@ add_library(service STATIC
4343
storage/ingestor/recipe/recipe_builtin.cc
4444
storage/ingestor/recipe/recipe_custom.cc
4545
storage/ingestor/recipe/recipe_parser.cc
46+
storage/issues/issue_callback.cc
47+
storage/issues/issue_service.cc
48+
storage/issues/issues.cc
4649
storage/management/project_access.cc
4750
storage/management/project_management.cc
4851
storage/deployment.cc
49-
storage/issues.cc
5052
storage/storage.cc
5153
storage/gitclone.cc
5254
storage/gitops.cc

src/service/database/database.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@
1212
#include <models/Report.h>
1313
#include <nlohmann/json.hpp>
1414
#include <service/error.h>
15-
#include <service/storage/issues.h>
15+
#include <service/storage/issues/issues.h>
1616

1717
using namespace drogon_model::postgres;
1818

@@ -135,7 +135,7 @@ namespace service {
135135

136136
// Issues
137137
drogon::Task<TaskResult<ProjectIssue>> getProjectIssue(std::string deploymentId, ProjectIssueLevel level, ProjectIssueType type,
138-
std::string path) const;
138+
std::string file) const;
139139
drogon::Task<std::vector<ProjectIssue>> getDeploymentIssues(std::string deploymentId) const;
140140
drogon::Task<std::unordered_map<std::string, int64_t>> getActiveProjectIssueStats(std::string projectId) const;
141141

src/service/database/database_issues.cc

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#include <service/storage/issues.h>
1+
#include <service/storage/issues/issues.h>
22
#include "database.h"
33

44
using namespace logging;
@@ -7,16 +7,16 @@ using namespace drogon::orm;
77

88
namespace service {
99
Task<TaskResult<ProjectIssue>> Database::getProjectIssue(const std::string deploymentId, const ProjectIssueLevel level,
10-
const ProjectIssueType type, const std::string path) const {
11-
co_return co_await handleDatabaseOperation([deploymentId, path, level, type](const DbClientPtr &client) -> Task<ProjectIssue> {
10+
const ProjectIssueType type, const std::string file) const {
11+
co_return co_await handleDatabaseOperation([deploymentId, file, level, type](const DbClientPtr &client) -> Task<ProjectIssue> {
1212
CoroMapper<ProjectIssue> mapper(client);
1313
mapper.limit(1);
1414

1515
auto criteria{Criteria(ProjectIssue::Cols::_deployment_id, CompareOperator::EQ, deploymentId) &&
1616
Criteria(ProjectIssue::Cols::_level, CompareOperator::EQ, enumToStr(level)) &&
1717
Criteria(ProjectIssue::Cols::_type, CompareOperator::EQ, enumToStr(type))};
18-
if (!path.empty()) {
19-
criteria = criteria && Criteria(ProjectIssue::Cols::_file, CompareOperator::EQ, path);
18+
if (!file.empty()) {
19+
criteria = criteria && Criteria(ProjectIssue::Cols::_file, CompareOperator::EQ, file);
2020
}
2121

2222
co_return co_await mapper.findOne(criteria);

src/service/project/resolved.h

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
#pragma once
22

3+
#include <nlohmann/json_fwd.hpp>
34
#include <models/Item.h>
45
#include <models/Project.h>
56
#include <models/ProjectVersion.h>
6-
#include <nlohmann/json_fwd.hpp>
7-
#include <service/project/project.h>
87
#include <service/cache.h>
98
#include <service/database/database.h>
10-
#include <service/util.h>
9+
#include <service/project/project.h>
1110
#include <service/project/format.h>
11+
#include <service/storage/issues/issue_callback.h>
12+
#include <service/util.h>
1213

1314
namespace service {
1415
struct FolderMetadataEntry {

src/service/storage/ingestor/ingestor.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
#include <service/error.h>
77
#include <service/project/resolved.h>
88
#include <service/storage/ingestor/recipe/recipe_parser.h>
9-
#include <service/storage/issues.h>
9+
#include <service/storage/issues/issue_callback.h>
1010

1111
#define INGESTOR_CONTENT_PATHS "Content paths"
1212
#define INGESTOR_TAGS "Tags"

src/service/storage/ingestor/recipe/recipe_parser.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
#pragma once
22

33
#include <service/project/resolved.h>
4-
#include <service/storage/issues.h>
4+
#include <service/storage/issues/issue_callback.h>
55
#include <service/util.h>
66
#include "game_recipes.h"
77

src/service/storage/issues.cc renamed to src/service/storage/issues/issue_callback.cc

Lines changed: 3 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,58 +1,17 @@
1-
#include "issues.h"
1+
#include "issue_callback.h"
22

3-
#include <service/database/database.h>
4-
#include <service/util.h>
5-
#include "models/ProjectIssue.h"
3+
#include "issue_service.h"
64

75
using namespace drogon;
86

97
namespace service {
10-
// clang-format off
11-
ENUM_FROM_TO_STR(ProjectIssueLevel,
12-
{ProjectIssueLevel::WARNING, "warning"},
13-
{ProjectIssueLevel::ERROR, "error"}
14-
)
15-
16-
ENUM_FROM_TO_STR(ProjectIssueType,
17-
{ProjectIssueType::META, "meta"},
18-
{ProjectIssueType::FILE, "file"},
19-
{ProjectIssueType::GIT_CLONE, "git_clone"},
20-
{ProjectIssueType::GIT_INFO, "git_info"},
21-
{ProjectIssueType::INGESTOR, "ingestor"},
22-
{ProjectIssueType::PAGE, "page"},
23-
{ProjectIssueType::INTERNAL, "internal"}
24-
)
25-
26-
ENUM_FROM_TO_STR(ProjectError,
27-
{ProjectError::OK, "ok"},
28-
{ProjectError::REQUIRES_AUTH, "requires_auth"},
29-
{ProjectError::NO_REPOSITORY, "no_repository"},
30-
{ProjectError::REPO_TOO_LARGE, "repo_too_large"},
31-
{ProjectError::NO_BRANCH, "no_branch"},
32-
{ProjectError::NO_PATH, "no_path"},
33-
{ProjectError::INVALID_META, "invalid_meta"},
34-
{ProjectError::PAGE_RENDER, "page_render"},
35-
{ProjectError::DUPLICATE_PAGE, "duplicate_page"},
36-
{ProjectError::UNKNOWN_RECIPE_TYPE, "unknown_recipe_type"},
37-
{ProjectError::INVALID_INGREDIENT, "invalid_ingredient"},
38-
{ProjectError::INVALID_FILE, "invalid_file"},
39-
{ProjectError::INVALID_FORMAT, "invalid_format"},
40-
{ProjectError::INVALID_RESLOC, "invalid_resloc"},
41-
{ProjectError::INVALID_VERSION_BRANCH, "invalid_version_branch"},
42-
{ProjectError::MISSING_PLATFORM_PROJECT, "missing_platform_project"},
43-
{ProjectError::NO_PAGE_TITLE, "no_page_title"},
44-
{ProjectError::INVALID_FRONTMATTER, "invalid_frontmatter"},
45-
{ProjectError::MISSING_REQUIRED_ATTRIBUTE, "missing_required_attribute"}
46-
)
47-
// clang-format on
48-
498
ProjectIssueCallback::ProjectIssueCallback(const std::string &id, const std::shared_ptr<spdlog::logger> &log) :
509
deploymentId_(id), logger_(log), hasErrors_(false) {}
5110

5211
Task<> addIssueStatic(const ProjectIssueLevel level, const ProjectIssueType type, const ProjectError subject, const std::string details,
5312
const std::string file, const std::string deploymentId, const std::shared_ptr<spdlog::logger> logger) {
5413
if (!deploymentId.empty()) {
55-
co_await addIssue(deploymentId, level, type, subject, details, file);
14+
co_await global::issues->addProjectIssueInternal(deploymentId, level, type, subject, details, file);
5615
}
5716

5817
const auto logLevel = level == ProjectIssueLevel::ERROR ? spdlog::level::err : spdlog::level::warn;
@@ -122,17 +81,4 @@ namespace service {
12281

12382
return json;
12483
}
125-
126-
Task<> addIssue(const std::string deploymentId, const ProjectIssueLevel level, const ProjectIssueType type, const ProjectError subject,
127-
const std::string details, const std::string file) {
128-
ProjectIssue issue;
129-
issue.setDeploymentId(deploymentId);
130-
issue.setLevel(enumToStr(level));
131-
issue.setType(enumToStr(type));
132-
issue.setSubject(enumToStr(subject));
133-
issue.setDetails(details);
134-
issue.setFile(file);
135-
136-
co_await global::database->addModel(issue);
137-
}
13884
}

src/service/storage/issues.h renamed to src/service/storage/issues/issue_callback.h

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,8 @@
11
#pragma once
22

3-
#include <models/Deployment.h>
4-
#include <nlohmann/json.hpp>
5-
#include <service/util.h>
3+
#include <service/project/project.h>
64

75
namespace service {
8-
enum class ProjectIssueLevel { WARNING, ERROR, UNKNOWN };
9-
std::string enumToStr(ProjectIssueLevel level);
10-
ProjectIssueLevel parseProjectIssueLevel(const std::string &level);
11-
12-
enum class ProjectIssueType { META, FILE, GIT_CLONE, GIT_INFO, PAGE, INGESTOR, INTERNAL, UNKNOWN };
13-
std::string enumToStr(ProjectIssueType type);
14-
ProjectIssueType parseProjectIssueType(const std::string &level);
15-
16-
// clang-format off
17-
enum class ProjectError {
18-
OK,
19-
REQUIRES_AUTH, NO_REPOSITORY, REPO_TOO_LARGE, NO_BRANCH, NO_PATH,
20-
INVALID_META, PAGE_RENDER,
21-
DUPLICATE_PAGE, UNKNOWN_RECIPE_TYPE, INVALID_INGREDIENT,
22-
INVALID_FILE, INVALID_FORMAT, INVALID_RESLOC, INVALID_VERSION_BRANCH,
23-
INVALID_FRONTMATTER,
24-
MISSING_PLATFORM_PROJECT, NO_PAGE_TITLE, MISSING_REQUIRED_ATTRIBUTE,
25-
UNKNOWN
26-
};
27-
// clang-format on
28-
std::string enumToStr(ProjectError status);
29-
ProjectError parseProjectError(const std::string &str);
30-
316
class ProjectIssueCallback {
327
public:
338
explicit ProjectIssueCallback(const std::string &, const std::shared_ptr<spdlog::logger> &);
@@ -66,7 +41,4 @@ namespace service {
6641
const std::filesystem::path absolutePath_;
6742
const std::filesystem::path path_;
6843
};
69-
70-
drogon::Task<> addIssue(std::string deploymentId, ProjectIssueLevel level, ProjectIssueType type, ProjectError subject,
71-
std::string details = "", std::string file = "");
7244
}

0 commit comments

Comments
 (0)