forked from devhub-tud/git-server
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request devhub-tud#7 from devhub-tud/build-deployment
Preparing for build-server deployment.
- Loading branch information
Showing
23 changed files
with
787 additions
and
21 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,6 @@ | |
.project | ||
.settings | ||
|
||
**/.classpath | ||
**/target/ | ||
**/*.db | ||
.classpath | ||
target/ | ||
*.db |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
163 changes: 163 additions & 0 deletions
163
src/main/java/nl/tudelft/ewi/devhub/server/backend/BuildsBackend.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,163 @@ | ||
package nl.tudelft.ewi.devhub.server.backend; | ||
|
||
import java.util.List; | ||
import java.util.concurrent.ConcurrentLinkedQueue; | ||
import java.util.concurrent.ScheduledExecutorService; | ||
import java.util.concurrent.ScheduledThreadPoolExecutor; | ||
import java.util.concurrent.TimeUnit; | ||
import java.util.concurrent.atomic.AtomicBoolean; | ||
|
||
import javax.inject.Inject; | ||
import javax.ws.rs.NotFoundException; | ||
|
||
import lombok.extern.slf4j.Slf4j; | ||
import nl.tudelft.ewi.build.client.BuildServerBackend; | ||
import nl.tudelft.ewi.build.jaxrs.models.BuildRequest; | ||
import nl.tudelft.ewi.devhub.server.database.controllers.BuildServers; | ||
import nl.tudelft.ewi.devhub.server.database.entities.BuildServer; | ||
import nl.tudelft.ewi.devhub.server.web.errors.ApiError; | ||
|
||
import com.google.common.collect.Queues; | ||
import com.google.inject.Provider; | ||
import com.google.inject.persist.Transactional; | ||
import com.google.inject.persist.UnitOfWork; | ||
|
||
/** | ||
* The {@link BuildServerClient} allows you to query and manipulate data from the build-server. | ||
*/ | ||
@Slf4j | ||
public class BuildsBackend { | ||
|
||
private final BuildServers buildServers; | ||
private final Provider<BuildSubmitter> submitters; | ||
private final ConcurrentLinkedQueue<BuildRequest> buildQueue; | ||
private final ScheduledExecutorService executor; | ||
private final AtomicBoolean running; | ||
|
||
@Inject | ||
BuildsBackend(BuildServers buildServers, Provider<BuildSubmitter> submitters) { | ||
this.buildServers = buildServers; | ||
this.submitters = submitters; | ||
this.buildQueue = Queues.newConcurrentLinkedQueue(); | ||
this.executor = new ScheduledThreadPoolExecutor(1); | ||
this.running = new AtomicBoolean(false); | ||
} | ||
|
||
public List<BuildServer> listActiveBuildServers() { | ||
return buildServers.listAll(); | ||
} | ||
|
||
public boolean authenticate(String name, String secret) { | ||
try { | ||
buildServers.findByCredentials(name, secret); | ||
return true; | ||
} | ||
catch (NotFoundException e) { | ||
return false; | ||
} | ||
} | ||
|
||
public void addBuildServer(BuildServer server) throws ApiError { | ||
try { | ||
buildServers.persist(server); | ||
} | ||
catch (Throwable e) { | ||
throw new ApiError("error.could-not-add-build-server"); | ||
} | ||
} | ||
|
||
@Transactional | ||
public void deleteBuildServer(long serverId) throws ApiError { | ||
try { | ||
BuildServer server = buildServers.findById(serverId); | ||
buildServers.delete(server); | ||
} | ||
catch (Throwable e) { | ||
throw new ApiError("error.could-not-remove-build-server"); | ||
} | ||
} | ||
|
||
public void offerBuild(BuildRequest request) { | ||
synchronized (running) { | ||
buildQueue.offer(request); | ||
if (running.compareAndSet(false, true)) { | ||
BuildSubmitter task = submitters.get(); | ||
task.initialize(this); | ||
executor.submit(task); | ||
} | ||
} | ||
} | ||
|
||
public void shutdown() throws InterruptedException { | ||
executor.shutdown(); | ||
executor.awaitTermination(1, TimeUnit.MINUTES); | ||
} | ||
|
||
private static class BuildSubmitter extends RunnableInUnitOfWork { | ||
|
||
private static final int NO_CAPACITY_DELAY = 5000; | ||
|
||
private final Provider<BuildServers> buildServersProvider; | ||
|
||
private BuildsBackend backend; | ||
|
||
@Inject | ||
BuildSubmitter(Provider<BuildServers> buildServersProvider, Provider<UnitOfWork> workProvider) { | ||
super(workProvider); | ||
this.buildServersProvider = buildServersProvider; | ||
} | ||
|
||
void initialize(BuildsBackend backend) { | ||
this.backend = backend; | ||
} | ||
|
||
@Override | ||
@Transactional | ||
protected void runInUnitOfWork() { | ||
ConcurrentLinkedQueue<BuildRequest> buildQueue = backend.buildQueue; | ||
AtomicBoolean running = backend.running; | ||
BuildServers buildServers = buildServersProvider.get(); | ||
|
||
try { | ||
while (!buildQueue.isEmpty()) { | ||
boolean delivered = false; | ||
BuildRequest buildRequest = buildQueue.peek(); | ||
List<BuildServer> allBuildServers = buildServers.listAll(); | ||
|
||
while (!allBuildServers.isEmpty()) { | ||
BuildServer buildServer = allBuildServers.remove(0); | ||
String host = buildServer.getHost(); | ||
String name = buildServer.getName(); | ||
String secret = buildServer.getSecret(); | ||
|
||
BuildServerBackend backend = new BuildServerBackend(host, name, secret); | ||
if (backend.offerBuildRequest(buildRequest)) { | ||
delivered = true; | ||
buildQueue.poll(); | ||
log.info("One build request was succesfully handed to: {}", name); | ||
break; | ||
} | ||
} | ||
|
||
if (!delivered) { | ||
try { | ||
log.info("All {} build servers at capacity. Queue size: {}", | ||
allBuildServers.size(), buildQueue.size()); | ||
|
||
Thread.sleep(NO_CAPACITY_DELAY); | ||
} | ||
catch (InterruptedException e) { | ||
log.warn("Sleep was interrupted..."); | ||
} | ||
} | ||
} | ||
} | ||
finally { | ||
synchronized (running) { | ||
running.set(false); | ||
} | ||
} | ||
} | ||
} | ||
|
||
} |
37 changes: 37 additions & 0 deletions
37
src/main/java/nl/tudelft/ewi/devhub/server/backend/RunnableInUnitOfWork.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,37 @@ | ||
package nl.tudelft.ewi.devhub.server.backend; | ||
|
||
import lombok.AllArgsConstructor; | ||
import lombok.extern.slf4j.Slf4j; | ||
|
||
import com.google.inject.Provider; | ||
import com.google.inject.persist.UnitOfWork; | ||
|
||
/** | ||
* A wrapper for a {@link java.lang.Runnable} where the call method is run within a | ||
* {@link com.google.inject.persist.UnitOfWork}; | ||
*/ | ||
@Slf4j | ||
@AllArgsConstructor | ||
public abstract class RunnableInUnitOfWork implements Runnable { | ||
|
||
private final Provider<UnitOfWork> workProvider; | ||
|
||
@Override | ||
public final void run() { | ||
UnitOfWork work = workProvider.get(); | ||
try { | ||
log.trace("Starting"); | ||
work.begin(); | ||
runInUnitOfWork(); | ||
} | ||
catch (Throwable e) { | ||
log.error(e.getMessage(), e); | ||
} | ||
finally { | ||
work.end(); | ||
log.trace("Finished"); | ||
} | ||
} | ||
|
||
protected abstract void runInUnitOfWork(); | ||
} |
53 changes: 53 additions & 0 deletions
53
src/main/java/nl/tudelft/ewi/devhub/server/database/controllers/BuildServers.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,53 @@ | ||
package nl.tudelft.ewi.devhub.server.database.controllers; | ||
|
||
import java.util.List; | ||
|
||
import javax.inject.Inject; | ||
import javax.persistence.EntityManager; | ||
import javax.ws.rs.NotFoundException; | ||
|
||
import nl.tudelft.ewi.devhub.server.database.entities.BuildServer; | ||
import nl.tudelft.ewi.devhub.server.database.entities.QBuildServer; | ||
|
||
import com.google.inject.persist.Transactional; | ||
|
||
public class BuildServers extends Controller<BuildServer> { | ||
|
||
@Inject | ||
public BuildServers(EntityManager entityManager) { | ||
super(entityManager); | ||
} | ||
|
||
@Transactional | ||
public List<BuildServer> listAll() { | ||
return query().from(QBuildServer.buildServer) | ||
.orderBy(QBuildServer.buildServer.name.asc()) | ||
.list(QBuildServer.buildServer); | ||
} | ||
|
||
@Transactional | ||
public BuildServer findById(long id) { | ||
BuildServer buildServer = query().from(QBuildServer.buildServer) | ||
.where(QBuildServer.buildServer.id.eq(id)) | ||
.singleResult(QBuildServer.buildServer); | ||
|
||
if (buildServer == null) { | ||
throw new NotFoundException(); | ||
} | ||
return buildServer; | ||
} | ||
|
||
@Transactional | ||
public BuildServer findByCredentials(String name, String secret) { | ||
BuildServer buildServer = query().from(QBuildServer.buildServer) | ||
.where(QBuildServer.buildServer.name.eq(name)) | ||
.where(QBuildServer.buildServer.secret.eq(secret)) | ||
.singleResult(QBuildServer.buildServer); | ||
|
||
if (buildServer == null) { | ||
throw new NotFoundException(); | ||
} | ||
return buildServer; | ||
} | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
35 changes: 35 additions & 0 deletions
35
src/main/java/nl/tudelft/ewi/devhub/server/database/entities/BuildServer.java
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
package nl.tudelft.ewi.devhub.server.database.entities; | ||
|
||
import javax.persistence.Column; | ||
import javax.persistence.Entity; | ||
import javax.persistence.GeneratedValue; | ||
import javax.persistence.GenerationType; | ||
import javax.persistence.Id; | ||
import javax.persistence.Table; | ||
import javax.validation.constraints.NotNull; | ||
|
||
import lombok.Data; | ||
|
||
@Data | ||
@Entity | ||
@Table(name = "build_servers") | ||
public class BuildServer { | ||
|
||
@Id | ||
@Column(name = "id") | ||
@GeneratedValue(strategy = GenerationType.IDENTITY) | ||
private long id; | ||
|
||
@NotNull | ||
@Column(name = "name") | ||
private String name; | ||
|
||
@NotNull | ||
@Column(name = "secret") | ||
private String secret; | ||
|
||
@NotNull | ||
@Column(name = "host") | ||
private String host; | ||
|
||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.