Skip to content

Commit ffc01a7

Browse files
authored
Merge pull request #3756 from akto-api-security/abhi/feat/ai-agent-jobs
feat: add account jobs support
2 parents 2d4626e + 189cf7d commit ffc01a7

File tree

13 files changed

+118
-643
lines changed

13 files changed

+118
-643
lines changed

apps/dashboard/src/main/java/com/akto/action/AIAgentConnectorImportAction.java

Lines changed: 18 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
package com.akto.action;
22

33
import com.akto.dao.context.Context;
4-
import com.akto.dto.jobs.AIAgentConnectorSyncJobParams;
5-
import com.akto.dto.jobs.Job;
6-
import com.akto.dto.jobs.JobExecutorType;
7-
import com.akto.jobs.JobScheduler;
4+
import com.akto.dao.jobs.AccountJobDao;
5+
import com.akto.dto.jobs.AccountJob;
86
import com.akto.log.LoggerMaker;
97
import com.akto.log.LoggerMaker.LogDb;
108
import com.opensymphony.xwork2.Action;
@@ -70,30 +68,28 @@ public String initiateImport() {
7068
? recurringIntervalSeconds
7169
: DEFAULT_RECURRING_INTERVAL_SECONDS;
7270

73-
// Schedule recurring job using JobScheduler
74-
Job job = JobScheduler.scheduleRecurringJob(
75-
Context.accountId.get(),
76-
new AIAgentConnectorSyncJobParams(
77-
connectorType,
78-
config,
79-
Context.now()
80-
),
81-
JobExecutorType.DASHBOARD,
82-
interval
71+
// Create entry in per-account jobs collection
72+
// Convert Map<String, String> config to Map<String, Object> for generic storage
73+
Map<String, Object> jobConfig = new HashMap<>(config);
74+
75+
AccountJob accountJob = new AccountJob(
76+
Context.accountId.get(), // accountId
77+
"AI_AGENT_CONNECTOR", // jobType (generic)
78+
connectorType, // subType (N8N, LANGCHAIN, COPILOT_STUDIO)
79+
jobConfig, // flexible config map
80+
interval, // recurringIntervalSeconds
81+
Context.now(), // createdAt
82+
Context.now() // lastUpdatedAt
8383
);
8484

85-
if (job == null) {
86-
loggerMaker.error("Failed to schedule recurring job for " + connectorType + " connector", LogDb.DASHBOARD);
87-
return Action.ERROR.toUpperCase();
88-
}
89-
90-
this.jobId = job.getId().toHexString();
91-
loggerMaker.info("Successfully scheduled recurring job for " + connectorType + " connector with job ID: " + this.jobId + ", interval: " + interval + "s", LogDb.DASHBOARD);
85+
AccountJobDao.instance.insertOne(accountJob);
86+
this.jobId = accountJob.getId().toHexString();
87+
loggerMaker.info("Successfully created account-level job for " + connectorType + " connector with job ID: " + this.jobId + ", interval: " + interval + "s", LogDb.DASHBOARD);
9288

9389
return Action.SUCCESS.toUpperCase();
9490

9591
} catch (Exception e) {
96-
loggerMaker.error("Error initiating " + connectorType + " import: " + e.getMessage(), LogDb.DASHBOARD);
92+
loggerMaker.error("Error creating account-level job for " + connectorType + " connector: " + e.getMessage(), LogDb.DASHBOARD);
9793
return Action.ERROR.toUpperCase();
9894
}
9995
}

libs/dao/src/main/java/com/akto/DaoInit.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
import com.akto.dao.*;
44
import com.akto.dao.audit_logs.ApiAuditLogsDao;
55
import com.akto.dao.billing.OrganizationsDao;
6+
import com.akto.dao.jobs.AccountJobDao;
67
import com.akto.dao.jobs.JobsDao;
78
import com.akto.dao.loaders.LoadersDao;
89
import com.akto.dao.metrics.MetricDataDao;
@@ -476,6 +477,7 @@ public static void createIndices() {
476477
PupeteerLogsDao.instance.createIndicesIfAbsent();
477478
SourceCodeVulnerabilitiesDao.instance.createIndicesIfAbsent();
478479
JobsDao.instance.createIndicesIfAbsent();
480+
AccountJobDao.instance.createIndicesIfAbsent();
479481
BidirectionalSyncSettingsDao.instance.createIndicesIfAbsent();
480482
MetricDataDao.instance.createIndicesIfAbsent();
481483
SensitiveSampleDataDao.instance.createIndicesIfAbsent();
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
package com.akto.dao.jobs;
2+
3+
import com.akto.dao.AccountsContextDao;
4+
import com.akto.dao.MCollection;
5+
import com.akto.dao.context.Context;
6+
import com.akto.dto.jobs.AccountJob;
7+
import com.mongodb.client.model.CreateCollectionOptions;
8+
9+
/**
10+
* DAO for generic account-level jobs collection.
11+
* This collection can be used by any feature that needs account-level job tracking.
12+
*/
13+
public class AccountJobDao extends AccountsContextDao<AccountJob> {
14+
15+
public static final AccountJobDao instance = new AccountJobDao();
16+
17+
@Override
18+
public String getCollName() {
19+
return "account_jobs";
20+
}
21+
22+
@Override
23+
public Class<AccountJob> getClassT() {
24+
return AccountJob.class;
25+
}
26+
27+
public void createIndicesIfAbsent() {
28+
String dbName = Context.accountId.get() + "";
29+
createCollectionIfAbsent(dbName, getCollName(), new CreateCollectionOptions());
30+
31+
// Index 1: Filter by job type, sort by creation date
32+
String[] fieldNames = {AccountJob.JOB_TYPE, AccountJob.CREATED_AT};
33+
MCollection.createIndexIfAbsent(getDBName(), getCollName(), fieldNames, false);
34+
35+
// Index 2: Filter by job type and sub-type, sort by creation date
36+
fieldNames = new String[]{AccountJob.JOB_TYPE, AccountJob.SUB_TYPE, AccountJob.CREATED_AT};
37+
MCollection.createIndexIfAbsent(getDBName(), getCollName(), fieldNames, false);
38+
}
39+
}

libs/dao/src/main/java/com/akto/dto/jobs/AIAgentConnectorSyncJobParams.java

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
package com.akto.dto.jobs;
2+
3+
import lombok.AllArgsConstructor;
4+
import lombok.Getter;
5+
import lombok.NoArgsConstructor;
6+
import lombok.Setter;
7+
import lombok.ToString;
8+
import org.bson.types.ObjectId;
9+
10+
import java.util.Map;
11+
12+
/**
13+
* Generic DTO for account-level jobs.
14+
* Can be used by any feature that needs account-level job tracking
15+
* (AI Agent Connectors, scheduled reports, data exports, etc.).
16+
*/
17+
@Getter
18+
@Setter
19+
@NoArgsConstructor
20+
@AllArgsConstructor
21+
@ToString
22+
public class AccountJob {
23+
24+
// Field name constants
25+
public static final String ID = "_id";
26+
public static final String ACCOUNT_ID = "accountId";
27+
public static final String JOB_TYPE = "jobType";
28+
public static final String SUB_TYPE = "subType";
29+
public static final String CONFIG = "config";
30+
public static final String RECURRING_INTERVAL_SECONDS = "recurringIntervalSeconds";
31+
public static final String CREATED_AT = "createdAt";
32+
public static final String LAST_UPDATED_AT = "lastUpdatedAt";
33+
34+
// Fields
35+
private ObjectId id; // Primary key
36+
private int accountId; // Account identifier
37+
private String jobType; // Generic job type (e.g., "AI_AGENT_CONNECTOR", "SCHEDULED_REPORT")
38+
private String subType; // Job sub-type (e.g., "N8N", "LANGCHAIN", "COPILOT_STUDIO")
39+
private Map<String, Object> config; // Flexible configuration (any data structure)
40+
private int recurringIntervalSeconds; // Recurrence interval (0 for non-recurring)
41+
private int createdAt; // Creation timestamp
42+
private int lastUpdatedAt; // Last update timestamp
43+
44+
/**
45+
* Constructor without id field (MongoDB will auto-generate the id).
46+
* Use this constructor when creating new AccountJob instances.
47+
*/
48+
public AccountJob(int accountId, String jobType, String subType, Map<String, Object> config,
49+
int recurringIntervalSeconds, int createdAt, int lastUpdatedAt) {
50+
this.accountId = accountId;
51+
this.jobType = jobType;
52+
this.subType = subType;
53+
this.config = config;
54+
this.recurringIntervalSeconds = recurringIntervalSeconds;
55+
this.createdAt = createdAt;
56+
this.lastUpdatedAt = lastUpdatedAt;
57+
}
58+
}

libs/dao/src/main/java/com/akto/dto/jobs/JobType.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,5 @@
33
public enum JobType {
44
JIRA_AUTO_CREATE_TICKETS,
55
TICKET_SYNC,
6-
PENDING_TESTS_ALERTS,
7-
AI_AGENT_CONNECTOR_SYNC
6+
PENDING_TESTS_ALERTS
87
}

libs/utils/src/main/java/com/akto/jobs/JobExecutorFactory.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
import com.akto.dto.jobs.JobParams;
44
import com.akto.dto.jobs.JobType;
5-
import com.akto.jobs.executors.AIAgentConnectorSyncJobExecutor;
65
import com.akto.jobs.executors.JiraTicketJobExecutor;
76
import com.akto.jobs.executors.PendingTestsAlertsJobExecutor;
87
import com.akto.jobs.executors.TicketSyncJobExecutor;
@@ -18,7 +17,6 @@ public class JobExecutorFactory {
1817
map.put(JobType.JIRA_AUTO_CREATE_TICKETS, JiraTicketJobExecutor.INSTANCE);
1918
map.put(JobType.TICKET_SYNC, TicketSyncJobExecutor.INSTANCE);
2019
map.put(JobType.PENDING_TESTS_ALERTS, PendingTestsAlertsJobExecutor.INSTANCE);
21-
map.put(JobType.AI_AGENT_CONNECTOR_SYNC, AIAgentConnectorSyncJobExecutor.INSTANCE);
2220

2321
registry = Collections.unmodifiableMap(map);
2422
}

0 commit comments

Comments
 (0)