Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto deploy feed version #361

Merged
merged 76 commits into from
Jun 15, 2021
Merged
Show file tree
Hide file tree
Changes from 60 commits
Commits
Show all changes
76 commits
Select commit Hold shift + click to select a range
526c126
feat(auto-deploy): auto-deploy to OTP when a new feed version is proc…
landonreed Dec 18, 2020
0f45633
Merge branch 'dev' into auto-deploy
Jan 12, 2021
21919cb
refactor: Initial auto deploy feed version work
Jan 18, 2021
f7bafa6
refactor(FeedVersionTest): Removed unused imports (hangover from test…
Jan 18, 2021
82b7a6d
refactor(Added an additional test): Added a unit test to cover high s…
Jan 19, 2021
ac16806
test: add mock GTFS that expires in 2099
landonreed Jan 19, 2021
3f3e9f9
refactor(Addressed PR feedback): Updated DB call and unit tests
Jan 20, 2021
c37cae0
refactor(AutoDeployFeedJob): Added fail status if job unable to be de…
Jan 20, 2021
e734c03
Merge branch 'dev' into auto-deploy
Jan 21, 2021
6b12c36
refactor(FeedVersion.java): use select distinct for checking error types
landonreed Jan 21, 2021
ce092d6
refactor: provide access to MonitorableJob#subjobs for testing
landonreed Jan 21, 2021
bddfa11
refactor(AutoDeployFeedJobTest): Updated assertions with expected text
Jan 21, 2021
da212c7
refactor(auto-deploy): entirely skip auto deploy job on certain condi…
landonreed Jan 21, 2021
b8d6d91
refactor(Addressed PR feedback): Addressed PR comments
Jan 25, 2021
67fd142
Merge branch 'auto-deploy' of https://github.com/ibi-group/datatools-…
Jan 25, 2021
853862f
refactor(ProcessSingleFeedJob): Added the missing DataManager import
Jan 25, 2021
93400d4
refactor(AutoDeployFeedJobTest): Removed '*' use in imports
Jan 27, 2021
30dde34
refactor(AutoDeployFeedJob): Updated method name
Jan 27, 2021
67cdad4
refactor(AutoDeployFeedJob): Removed unused import
Jan 27, 2021
7e59914
Merge branch 'dev' into auto-deploy
Jan 28, 2021
f3b90b6
refactor(AutoDeployJob): check for active feed fetches before deploying
landonreed Feb 11, 2021
702a5eb
refactor(Auto deploy race conditions unit test): Additional unit test…
Feb 18, 2021
8e27a03
refactor(Addressed PR feedback): Updated how the MonitorableJob messa…
Feb 19, 2021
f172917
refactor(AutoDeployFeedJobTest): Updated base gtfs zip file used to t…
Feb 22, 2021
629ffd2
refactor(AutoDeployFeedJob): Created separate feed sources for each u…
Feb 23, 2021
30e6dcf
refactor(AutoDeployFeedJobTest): Created separate server, project and…
Feb 23, 2021
51f7eda
refactor(AutoDeployFeedJobTest): Fixed incorrect id assignment
Feb 23, 2021
70014be
refactor(AutoDeployFeedJobTest): Reduced the number of feed sources u…
Feb 23, 2021
84586e2
refactor(MonitorableJob): avoid duplicate completion in completeSucce…
landonreed Feb 23, 2021
1d21bf4
refactor(Updated approach to auto deploy): Auto deploy logic now hand…
Mar 17, 2021
135a592
refactor(Fixed merge conflicts): Fixed merge conflicts in DeployJob
Mar 17, 2021
8ba6fc5
Merge branch 'dev' into auto-deploy
Mar 22, 2021
3f9d8b5
refactor(AutoDeployFeedJobTest): Updated junit annotations
Mar 22, 2021
00e451c
Update src/main/java/com/conveyal/datatools/manager/jobs/AutoDeployFe…
Mar 23, 2021
2cb11ea
refactor(Addressed PR feedback): Updated the auto deploy job logic an…
Mar 25, 2021
238d4c6
Update src/test/resources/com/conveyal/datatools/gtfs/fake-agency-wit…
Mar 29, 2021
de1ce5c
Update src/test/java/com/conveyal/datatools/manager/jobs/AutoDeployFe…
Mar 29, 2021
6987ec9
refactor(Addressed PR feedback): Update to focus on deployment feed v…
Mar 29, 2021
801c898
refactor(AutoDeployJob): Updated to use feed sources associated with …
Mar 30, 2021
e5d3a4d
refactor(FeedVersion): Corrected comments
Mar 30, 2021
1e38a4c
refactor: change some logic in AutoDeployJob
evansiroky Mar 31, 2021
9efd934
Merge pull request #372 from ibi-group/auto-deploy-eas
Mar 31, 2021
1a282cf
Update src/main/java/com/conveyal/datatools/manager/jobs/AutoDeployJo…
Mar 31, 2021
1175cdb
Merge branch 'dev' into auto-deploy
Apr 7, 2021
24f1725
refactor(Addressed PR feedback): Addressed PR feedback
Apr 8, 2021
3c3f66b
refactor: add abstract FeedSourceJob and FeedVersionJob classes
landonreed Apr 9, 2021
afaf3bc
refactor(FeedSource.java): Streamlined job instanceof check
Apr 9, 2021
243ef63
Update src/main/java/com/conveyal/datatools/manager/jobs/ProcessSingl…
Apr 9, 2021
413a2b4
Update src/main/java/com/conveyal/datatools/common/status/FeedSourceJ…
Apr 12, 2021
fa3d584
Update src/main/java/com/conveyal/datatools/common/status/FeedVersion…
Apr 12, 2021
6fd03b5
refactor(FeedSource.java): Reverted job in progress check back to a m…
Apr 13, 2021
6cc2657
Merge branch 'auto-deploy' of https://github.com/ibi-group/datatools-…
Apr 13, 2021
38cb1c2
refactor(FeedSource.java): Removed obsolete comments/code
Apr 13, 2021
baad68a
refactor(Added pinned feed versions to Deployment): Added pinned feed…
Apr 15, 2021
cafb0e5
Update src/main/java/com/conveyal/datatools/manager/models/Deployment…
Apr 19, 2021
2aea8ae
refactor(AutoDeployJob.java): Removed notification regarding advancin…
Apr 21, 2021
e65a337
refactor(Addressed PR feedback): Addressed PR feedback
Apr 28, 2021
83d1134
refactor: consolidate AutoDeployJob initialization in ProcessSingleFe…
evansiroky Apr 28, 2021
2d3b82b
Merge pull request #375 from ibi-group/auto-deploy-eas
Apr 30, 2021
0fb54ca
test: fix GisExportJobTest
evansiroky May 2, 2021
d209aca
refactor(auto-deploy): add code to end auto-deployment in certain cases
evansiroky May 3, 2021
5818355
test: fix a failing test
evansiroky May 3, 2021
1c429e8
refactor: move post-deployment auto-deploy logic into method
evansiroky May 4, 2021
3083c5f
Merge pull request #377 from ibi-group/auto-deploy-eas
May 4, 2021
db462d0
refactor(auto-deploy): refactor a few things to improve auto-deployment
evansiroky May 7, 2021
c4d04c7
refactor: address PR review comments
evansiroky May 11, 2021
03e9d2e
Merge pull request #381 from ibi-group/auto-deploy-eas
evansiroky May 11, 2021
0f3f36f
refactor: make sure deployment is persisted in AutoDeployJob
evansiroky May 11, 2021
276aa46
Merge branch 'dev' into auto-deploy
May 21, 2021
2292e72
refactor: add FeedSource#versions
landonreed May 26, 2021
68e678c
refactor: Apply suggestions from code review
landonreed May 27, 2021
0a82db8
refactor(FeedSource): change versions to versionCount
landonreed May 28, 2021
51cca5c
Merge branch 'dev' into auto-deploy
Jun 1, 2021
e88392c
Merge branch 'dev' into auto-deploy
Jun 1, 2021
d196cc4
refactor(Fixed merge conflicts): Fixed merge conflicts
Jun 15, 2021
38c1b43
refactor(HandleCorruptGTFSFileTest.java): Updated test to include pro…
Jun 15, 2021
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
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.datatools.common.status;

import com.conveyal.datatools.manager.auth.Auth0UserProfile;

/**
* This class should be used for any job that operates on a FeedSource.
*/
public abstract class FeedSourceJob extends MonitorableJob {
br648 marked this conversation as resolved.
Show resolved Hide resolved
public FeedSourceJob(Auth0UserProfile owner, String name, JobType type) {
super(owner, name, type);
}

public abstract String getFeedSourceId();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
package com.conveyal.datatools.common.status;

import com.conveyal.datatools.manager.auth.Auth0UserProfile;

/**
* This class should be used for any job that operates on a FeedVersion.
*/
public abstract class FeedVersionJob extends FeedSourceJob {
br648 marked this conversation as resolved.
Show resolved Hide resolved
public FeedVersionJob(Auth0UserProfile owner, String name, JobType type) {
super(owner, name, type);
}

public abstract String getFeedVersionId();
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@

import com.conveyal.datatools.manager.DataManager;
import com.conveyal.datatools.manager.auth.Auth0UserProfile;
import com.fasterxml.jackson.annotation.JsonIgnore;
import com.fasterxml.jackson.annotation.JsonProperty;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bson.codecs.pojo.annotations.BsonIgnore;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

Expand All @@ -29,8 +31,8 @@ public abstract class MonitorableJob implements Runnable, Serializable {
// Public fields will be serialized over HTTP API and visible to the web client
public final JobType type;
public File file;
public String parentJobId;
public JobType parentJobType;
protected String parentJobId;
protected JobType parentJobType;
// Status is not final to allow some jobs to have extra status fields.
public Status status = new Status();
// Name is not final in case it needs to be amended during job processing.
Expand All @@ -41,9 +43,10 @@ public abstract class MonitorableJob implements Runnable, Serializable {
* Additional jobs that will be run after the main logic of this job has completed.
* This job is not considered entirely completed until its sub-jobs have all completed.
*/
protected List<MonitorableJob> subJobs = new ArrayList<>();
final private List<MonitorableJob> subJobs = new ArrayList<>();

public enum JobType {
AUTO_DEPLOY_FEED_VERSION,
UNKNOWN_TYPE,
ARBITRARY_FEED_TRANSFORM,
BUILD_TRANSPORT_NETWORK,
Expand Down Expand Up @@ -113,6 +116,11 @@ public String retrieveEmail() {
return this.owner.getEmail();
}

@JsonIgnore @BsonIgnore
public List<MonitorableJob> getSubJobs() {
return subJobs;
}

public File retrieveFile () {
return file;
}
Expand Down Expand Up @@ -288,15 +296,16 @@ private String getCallingMethodTrace() {
* Shorthand method to update status object on successful job completion.
*/
public void completeSuccessfully(String message) {
this.complete(false, message);
// Do not overwrite the message (and other fields), if the job has already been completed.
if (!this.completed) this.complete(false, message);
}

/**
* Set job status to completed with error and message information.
*/
private void complete(boolean isError, String message) {
this.error = isError;
// Skip message update if null.
// Skip message update if the job message is null or the message has already been defined.
if (message != null) this.message = message;
this.percentComplete = 100;
this.completed = true;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,19 @@
package com.conveyal.datatools.editor.datastore;

import com.conveyal.datatools.editor.models.transit.*;

import com.conveyal.datatools.editor.models.transit.Agency;
import com.conveyal.datatools.editor.models.transit.AttributeAvailabilityType;
import com.conveyal.datatools.editor.models.transit.EditorFeed;
import com.conveyal.datatools.editor.models.transit.Fare;
import com.conveyal.datatools.editor.models.transit.Route;
import com.conveyal.datatools.editor.models.transit.ScheduleException;
import com.conveyal.datatools.editor.models.transit.ServiceCalendar;
import com.conveyal.datatools.editor.models.transit.StatusType;
import com.conveyal.datatools.editor.models.transit.Stop;
import com.conveyal.datatools.editor.models.transit.StopTime;
import com.conveyal.datatools.editor.models.transit.Trip;
import com.conveyal.datatools.editor.models.transit.TripPattern;
import com.conveyal.datatools.editor.models.transit.TripPatternStop;
import com.conveyal.datatools.editor.utils.GeoUtils;
import com.conveyal.gtfs.GTFSFeed;
import com.conveyal.gtfs.model.CalendarDate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
import com.conveyal.datatools.manager.models.Project;
import com.conveyal.datatools.manager.persistence.Persistence;
import com.conveyal.datatools.manager.utils.json.JsonManager;
import com.mongodb.client.FindIterable;
import org.bson.Document;
import org.eclipse.jetty.http.HttpStatus;
import org.slf4j.Logger;
Expand Down Expand Up @@ -49,7 +50,7 @@
*/
public class DeploymentController {
private static final Logger LOG = LoggerFactory.getLogger(DeploymentController.class);
private static Map<String, DeployJob> deploymentJobsByServer = new HashMap<>();
private static final Map<String, DeployJob> deploymentJobsByServer = new HashMap<>();

/**
* Gets the deployment specified by the request's id parameter and ensure that user has access to the
Expand Down Expand Up @@ -376,6 +377,42 @@ private static boolean terminateEC2InstanceForDeployment(Request req, Response r
return true;
}

/**
* Queue a new {@link DeployJob} if there are no conflicting jobs assigned to the specified server.
* @param deployJob new deploy job to queue
* @return whether the deploy job was successfully queued or not
*/
public static boolean queueDeployJob(DeployJob deployJob) {
String serverId = deployJob.getServerId();
// Check that we can deploy to the specified target. (Any deploy job for the target that is presently active will
// cause a halt.)
if (deploymentJobsByServer.containsKey(serverId)) {
// There is a deploy job for the server. Check if it is active.
DeployJob conflictingDeployJob = deploymentJobsByServer.get(serverId);
if (conflictingDeployJob != null && !conflictingDeployJob.status.completed) {
// Another deploy job is actively being deployed to the server target.
LOG.error("New deploy job will not be queued due to active deploy job in progress.");
return false;
}
}

// For any previous deployments sent to the server/router combination, set deployedTo to null because
// this new one will overwrite it. NOTE: deployedTo for the current deployment will only be updated after the
// successful completion of the deploy job.
FindIterable<Deployment> deploymentsWithSameTarget = Deployment.retrieveDeploymentForServerAndRouterId(
serverId,
deployJob.getDeployment().routerId
);
for (Deployment oldDeployment : deploymentsWithSameTarget) {
LOG.info("Setting deployment target to null for id={}", oldDeployment.id);
Persistence.deployments.updateField(oldDeployment.id, "deployedTo", null);
}
// Finally, add deploy job to the heavy executor.
DataManager.heavyExecutor.execute(deployJob);
deploymentJobsByServer.put(serverId, deployJob);
return true;
}

/**
* HTTP controller to fetch information about provided EC2 machines that power ELBs running a trip planner.
*/
Expand All @@ -396,8 +433,9 @@ private static String deploy (Request req, Response res) {
String target = req.params("target");
Deployment deployment = getDeploymentWithPermissions(req, res);
Project project = Persistence.projects.getById(deployment.projectId);
if (project == null)
if (project == null) {
logMessageAndHalt(req, 400, "Internal reference error. Deployment's project ID is invalid");
}
// Get server by ID
OtpServer otpServer = Persistence.servers.getById(target);
if (otpServer == null) {
Expand All @@ -411,23 +449,6 @@ private static String deploy (Request req, Response res) {
logMessageAndHalt(req, 401, "User not authorized to deploy to admin-only target OTP server.");
}

// Check that we can deploy to the specified target. (Any deploy job for the target that is presently active will
// cause a halt.)
if (deploymentJobsByServer.containsKey(target)) {
// There is a deploy job for the server. Check if it is active.
DeployJob deployJob = deploymentJobsByServer.get(target);
if (deployJob != null && !deployJob.status.completed) {
// Job for the target is still active! Send a 202 to the requester to indicate that it is not possible
// to deploy to this target right now because someone else is deploying.
String message = String.format(
"Will not process request to deploy %s. Deployment currently in progress for target: %s",
deployment.name,
target);
LOG.warn(message);
logMessageAndHalt(req, HttpStatus.ACCEPTED_202, message);
}
}

// Get the URLs to deploy to.
List<String> targetUrls = otpServer.internalUrl;
if ((targetUrls == null || targetUrls.isEmpty()) && (otpServer.s3Bucket == null || otpServer.s3Bucket.isEmpty())) {
Expand All @@ -438,19 +459,17 @@ private static String deploy (Request req, Response res) {
);
}

// For any previous deployments sent to the server/router combination, set deployedTo to null because
// this new one will overwrite it. NOTE: deployedTo for the current deployment will only be updated after the
// successful completion of the deploy job.
for (Deployment oldDeployment : Deployment.retrieveDeploymentForServerAndRouterId(target, deployment.routerId)) {
LOG.info("Setting deployment target to null id={}", oldDeployment.id);
Persistence.deployments.updateField(oldDeployment.id, "deployedTo", null);
}

// Execute the deployment job and keep track of it in the jobs for server map.
DeployJob job = new DeployJob(deployment, userProfile, otpServer);
DataManager.heavyExecutor.execute(job);
deploymentJobsByServer.put(target, job);

if (!queueDeployJob(job)) {
// Job for the target is still active! Send a 202 to the requester to indicate that it is not possible
// to deploy to this target right now because someone else is deploying.
String message = String.format(
"Will not process request to deploy %s. Deployment currently in progress for target: %s",
br648 marked this conversation as resolved.
Show resolved Hide resolved
deployment.name,
target);
logMessageAndHalt(req, HttpStatus.ACCEPTED_202, message);
}
return SparkUtils.formatJobMessage(job.jobId, "Deployment initiating.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,16 +12,13 @@
import spark.Request;
import spark.Response;

import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

import static com.conveyal.datatools.common.utils.SparkUtils.logMessageAndHalt;
import static spark.Spark.delete;
import static spark.Spark.get;

/**
Expand Down
Loading