├── .gitignore ├── .ruby-version ├── .travis.yml ├── .yourbase.yml ├── LICENSE ├── README.md ├── findbugs-exclude.xml ├── gearman-client ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── johnewart │ │ └── gearman │ │ └── client │ │ ├── NetworkGearmanClient.java │ │ ├── NetworkGearmanWorker.java │ │ └── NetworkGearmanWorkerPool.java │ └── test │ └── java │ └── net │ └── johnewart │ └── gearman │ └── client │ └── NetworkGearmanClientTest.java ├── gearman-common ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── johnewart │ │ └── gearman │ │ ├── common │ │ ├── Job.java │ │ ├── JobState.java │ │ ├── JobStatus.java │ │ ├── client │ │ │ └── AbstractGearmanClient.java │ │ ├── events │ │ │ ├── GearmanClientEventListener.java │ │ │ └── WorkEvent.java │ │ ├── interfaces │ │ │ ├── EngineClient.java │ │ │ ├── EngineWorker.java │ │ │ ├── GearmanClient.java │ │ │ ├── GearmanFunction.java │ │ │ ├── GearmanWorker.java │ │ │ └── JobHandleFactory.java │ │ └── packets │ │ │ ├── Packet.java │ │ │ ├── PacketFactory.java │ │ │ ├── request │ │ │ ├── CanDo.java │ │ │ ├── CanDoTimeout.java │ │ │ ├── CantDo.java │ │ │ ├── EchoRequest.java │ │ │ ├── GetStatus.java │ │ │ ├── GrabJob.java │ │ │ ├── GrabJobAll.java │ │ │ ├── GrabJobUniq.java │ │ │ ├── OptionRequest.java │ │ │ ├── PreSleep.java │ │ │ ├── RequestPacket.java │ │ │ ├── ResetAbilities.java │ │ │ ├── SetClientId.java │ │ │ └── SubmitJob.java │ │ │ └── response │ │ │ ├── EchoResponse.java │ │ │ ├── JobAssign.java │ │ │ ├── JobAssignAll.java │ │ │ ├── JobAssignUniq.java │ │ │ ├── JobCreated.java │ │ │ ├── NoJob.java │ │ │ ├── NoOp.java │ │ │ ├── OptionResponse.java │ │ │ ├── ResponsePacket.java │ │ │ ├── StatusRes.java │ │ │ ├── WorkCompleteResponse.java │ │ │ ├── WorkDataResponse.java │ │ │ ├── WorkExceptionResponse.java │ │ │ ├── WorkFailResponse.java │ │ │ ├── WorkResponse.java │ │ │ ├── WorkStatus.java │ │ │ └── WorkWarningResponse.java │ │ ├── constants │ │ ├── GearmanConstants.java │ │ ├── JobPriority.java │ │ ├── PacketMagic.java │ │ └── PacketType.java │ │ ├── exceptions │ │ ├── JobSubmissionException.java │ │ ├── NoServersAvailableException.java │ │ ├── WorkException.java │ │ ├── WorkExceptionException.java │ │ └── WorkFailException.java │ │ ├── net │ │ ├── Connection.java │ │ ├── ConnectionFactory.java │ │ └── ConnectionPool.java │ │ └── util │ │ └── ByteArray.java │ └── test │ └── java │ └── net │ └── johnewart │ └── gearman │ └── common │ ├── PacketFactoryTest.java │ ├── PacketTest.java │ └── net │ ├── ConnectionPoolTest.java │ └── ConnectionTest.java ├── gearman-embedded-server ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── johnewart │ └── gearman │ └── embedded │ ├── EmbeddedGearmanClient.java │ ├── EmbeddedGearmanServer.java │ └── EmbeddedGearmanWorker.java ├── gearman-engine ├── pom.xml └── src │ ├── main │ └── java │ │ └── net │ │ └── johnewart │ │ └── gearman │ │ └── engine │ │ ├── core │ │ ├── JobAction.java │ │ ├── JobManager.java │ │ ├── JobPool.java │ │ ├── LocalJobPool.java │ │ ├── QueuedJob.java │ │ ├── UniqueIdFactory.java │ │ └── WorkerPool.java │ │ ├── exceptions │ │ ├── EnqueueException.java │ │ ├── IllegalJobStateTransitionException.java │ │ ├── JobQueueFactoryException.java │ │ ├── PersistenceException.java │ │ └── QueueFullException.java │ │ ├── healthchecks │ │ └── RedisHealthCheck.java │ │ ├── metrics │ │ ├── MetricsEngine.java │ │ └── QueueMetrics.java │ │ ├── queue │ │ ├── JobQueue.java │ │ ├── PersistedJobQueue.java │ │ ├── factories │ │ │ ├── DynamoDBPersistedJobQueueFactory.java │ │ │ ├── JobQueueFactory.java │ │ │ ├── MemoryJobQueueFactory.java │ │ │ ├── PostgreSQLPersistedJobQueueFactory.java │ │ │ └── RedisPersistedJobQueueFactory.java │ │ └── persistence │ │ │ ├── DynamoDBPersistenceEngine.java │ │ │ ├── MemoryPersistenceEngine.java │ │ │ ├── PersistenceEngine.java │ │ │ ├── PostgresPersistenceEngine.java │ │ │ └── RedisPersistenceEngine.java │ │ ├── storage │ │ ├── ExceptionData.java │ │ ├── ExceptionStorageEngine.java │ │ ├── MemoryExceptionStorageEngine.java │ │ ├── NoopExceptionStorageEngine.java │ │ └── PostgresExceptionStorageEngine.java │ │ └── util │ │ ├── EqualsLock.java │ │ ├── LocalJobHandleFactory.java │ │ └── LocalUniqueIdFactory.java │ └── test │ └── java │ └── net │ └── johnewart │ └── gearman │ └── engine │ ├── JobHandleFactoryTest.java │ ├── JobManagerTest.java │ ├── JobQueueTest.java │ ├── MemoryQueueTest.java │ ├── QueuedJobTest.java │ └── factories │ ├── JobFactory.java │ ├── TestJobHandleFactory.java │ └── TestUniqueIdFactory.java ├── gearman-example ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── johnewart │ └── gearman │ └── example │ ├── ClientDemo.java │ ├── EmbeddedServerDemo.java │ ├── WorkerDemo.java │ └── WorkerPoolDemo.java ├── gearman-integration ├── README.md ├── pom.xml └── src │ └── main │ └── java │ └── net │ └── johnewart │ └── gearman │ └── integ │ ├── BasicServerIntegrationTest.java │ ├── ClusterIntegrationTest.java │ ├── ReverseFunc.java │ └── WorkerRunner.java ├── gearman-server ├── config-1.yml ├── config-2.yml ├── config-dynamodb-local.yml ├── config-dynamodb.yml ├── config-nodebug.yml ├── config-postgres.yml ├── config-redis.yml ├── config.yml ├── pom.xml └── src │ ├── main │ ├── java │ │ └── net │ │ │ └── johnewart │ │ │ └── gearman │ │ │ └── server │ │ │ ├── GearmanDaemon.java │ │ │ ├── cluster │ │ │ ├── config │ │ │ │ ├── ClusterConfiguration.java │ │ │ │ └── HazelcastConfiguration.java │ │ │ ├── core │ │ │ │ ├── ClusterJobManager.java │ │ │ │ ├── HazelcastJob.java │ │ │ │ └── WorkMessage.java │ │ │ ├── queue │ │ │ │ ├── HazelcastJobQueue.java │ │ │ │ └── factories │ │ │ │ │ └── HazelcastJobQueueFactory.java │ │ │ ├── util │ │ │ │ ├── HazelcastJobHandleFactory.java │ │ │ │ └── HazelcastUniqueIdFactory.java │ │ │ └── web │ │ │ │ └── ClusterWebListener.java │ │ │ ├── config │ │ │ ├── DefaultServerConfiguration.java │ │ │ ├── ExceptionStoreConfiguration.java │ │ │ ├── GearmanServerConfiguration.java │ │ │ ├── PersistenceEngineConfiguration.java │ │ │ ├── ServerConfiguration.java │ │ │ └── persistence │ │ │ │ ├── DynamoDBConfiguration.java │ │ │ │ ├── PostgreSQLConfiguration.java │ │ │ │ └── RedisConfiguration.java │ │ │ ├── core │ │ │ └── JobTracker.java │ │ │ ├── net │ │ │ ├── Decoder.java │ │ │ ├── Encoder.java │ │ │ ├── GearmanServerInitializer.java │ │ │ ├── NetworkEngineClient.java │ │ │ ├── NetworkEngineWorker.java │ │ │ ├── NetworkManager.java │ │ │ ├── PacketHandler.java │ │ │ ├── ServerListener.java │ │ │ └── ssl │ │ │ │ ├── GearmanKeyStore.java │ │ │ │ ├── GearmanSslContextFactory.java │ │ │ │ └── GearmanTrustManagerFactory.java │ │ │ ├── util │ │ │ ├── JobQueueMetrics.java │ │ │ ├── JobQueueMonitor.java │ │ │ ├── JobQueueSnapshot.java │ │ │ ├── NoopJobQueueMonitor.java │ │ │ ├── SnapshottingJobQueueMonitor.java │ │ │ └── SystemSnapshot.java │ │ │ └── web │ │ │ ├── ClusterServlet.java │ │ │ ├── ClusterView.java │ │ │ ├── DashboardServlet.java │ │ │ ├── DateFormatter.java │ │ │ ├── ExceptionsServlet.java │ │ │ ├── ExceptionsView.java │ │ │ ├── GearmanServlet.java │ │ │ ├── JobQueueServlet.java │ │ │ ├── JobQueueStatusView.java │ │ │ ├── NumberFormatter.java │ │ │ ├── StatusView.java │ │ │ ├── SystemStatusView.java │ │ │ └── WebListener.java │ └── resources │ │ ├── logback.xml │ │ └── net │ │ └── johnewart │ │ └── gearman │ │ └── server │ │ └── web │ │ └── templates │ │ ├── cluster.ftl │ │ ├── css │ │ ├── admin.css │ │ ├── chart.css │ │ ├── extensions.css │ │ ├── jquery-ui.css │ │ └── rickshaw.min.css │ │ ├── d3.v3.min.js │ │ ├── exceptions.ftl │ │ ├── index.ftl │ │ ├── jquery-ui.min.js │ │ ├── jquery.min.js │ │ ├── js │ │ └── charts.js │ │ ├── layout.ftl │ │ ├── nocluster.ftl │ │ ├── noexceptions.ftl │ │ ├── queue.ftl │ │ ├── queues.ftl │ │ ├── rickshaw.extensions.js │ │ ├── rickshaw.js │ │ ├── rickshaw.min.js │ │ └── styles.ftl │ └── test │ └── java │ └── net │ └── johnewart │ └── gearman │ └── server │ ├── JobFactory.java │ ├── NetworkManagerTest.java │ ├── cluster │ └── util │ │ └── HazelcastJobHandleFactoryTest.java │ └── net │ ├── DecoderTest.java │ └── EncoderTest.java ├── misc ├── dashboard.jpg ├── queue.jpg └── queues.jpg └── pom.xml /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | *.class 3 | *.iml 4 | gearman-client/target 5 | gearman-common/target 6 | gearman-example/target 7 | gearman-server/target 8 | coverage 9 | target 10 | -------------------------------------------------------------------------------- /.ruby-version: -------------------------------------------------------------------------------- 1 | 2.1.0 2 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: java 2 | sudo: false 3 | jdk: 4 | - oraclejdk9 5 | 6 | -------------------------------------------------------------------------------- /.yourbase.yml: -------------------------------------------------------------------------------- 1 | dependencies: 2 | build: 3 | - java:8.202.08 4 | - maven:3.3.3 5 | 6 | build_targets: 7 | - name: tests 8 | commands: 9 | - mvn package 10 | 11 | ci: 12 | builds: 13 | - name: unit_tests 14 | build_target: tests 15 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | Gearman Java Implementation 2 | =========================== 3 | 4 | Test 5 | 6 | [](https://travis-ci.org/johnewart/gearman-java) 8 | 9 | An implementation of the [gearman protocol](http://www.gearman.org) server, client, and worker in Java. Features include: 10 | 11 | * Pluggable persistent storage mechanism currently supporting: 12 | * PostgreSQL 13 | * Redis 14 | * Memory-only 15 | * Web-based UI dashboard 16 | * Metrics using [java metrics](https://github.com/codahale/metrics) 17 | * Multi-threaded server using Netty for high-performance network I/O 18 | * High-performance - on a single m3.2xlarge EC2 instance with 8 on-box Ruby 19 | clients it has achieved over 11,000 jobs per second with in-memory 20 | storage 21 | 22 | 23 | Getting Started 24 | --------------- 25 | 26 | Quick start: 27 | 28 | 1. Download the [latest pre-built SNAPSHOT release](https://oss.sonatype.org/content/repositories/snapshots/net/johnewart/gearman/gearman-server/) from the Sonatype snapshots repository 29 | 2. Run java -jar gearman-server-VERSION.jar 30 | 3. This will default to port 4730 and memory-only persistence, with snapshotting and the web interface listening on port 8080 31 | 32 | If you want to use more advanced features, see the example config.yml 33 | files in [the gearman-server sub-project](https://github.com/johnewart/gearman-java/tree/master/gearman-server) 34 | 35 | 36 | Web Interface 37 | ------------- 38 | 39 | Some of the issues that I've run into in the past have been related to visibility into job queues. To address this, I've added a web management console that lets you see the state of the system. For small installations this is a nice option because it doesn't require you to setup or have any external monitoring systems. Some screenshots here: 40 | 41 | ### Main Dashboard 42 | 43 |  44 | 45 | ### All Queues 46 | 47 |  48 | 49 | ### Per-Queue Status 50 | 51 |  52 | 53 | 54 | Contributing 55 | ------------ 56 | 57 | Feel free to fork and submit pull requests, or test and submit bug reports. 58 | 59 | Author 60 | ------- 61 | 62 | John Ewart [http://johnewart.net](http://johnewart.net) 63 | 64 | Contributors 65 | ------------ 66 | 67 | Some tiny portions of this project leverage code from the java-gearman-service project. 68 | -------------------------------------------------------------------------------- /findbugs-exclude.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /gearman-client/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | gearman-java 7 | net.johnewart.gearman 8 | 0.8.11-SNAPSHOT 9 | 10 | 4.0.0 11 | jar 12 | 13 | gearman-client 14 | 15 | 16 | 17 | net.johnewart.gearman 18 | gearman-common 19 | ${project.version} 20 | 21 | 22 | ch.qos.logback 23 | logback-classic 24 | 1.2.0 25 | 26 | 27 | -------------------------------------------------------------------------------- /gearman-common/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | gearman-java 7 | net.johnewart.gearman 8 | 0.8.11-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | gearman-common 13 | 14 | 15 | 1.7.2 16 | 1.2.0 17 | 2.4.2 18 | 4.1.42.Final 19 | 20 | 21 | 22 | 23 | io.netty 24 | netty-all 25 | ${netty.version} 26 | 27 | 28 | com.google.guava 29 | guava 30 | 13.0.1 31 | 32 | 33 | org.slf4j 34 | jul-to-slf4j 35 | ${slf4j.version} 36 | 37 | 38 | ch.qos.logback 39 | logback-core 40 | ${logback.version} 41 | 42 | 43 | ch.qos.logback 44 | logback-classic 45 | ${logback.version} 46 | 47 | 48 | org.slf4j 49 | log4j-over-slf4j 50 | ${slf4j.version} 51 | 52 | 53 | com.fasterxml.jackson.jaxrs 54 | jackson-jaxrs-json-provider 55 | ${jackson.version} 56 | 57 | 58 | junit 59 | junit 60 | 4.13.1 61 | 62 | 63 | org.mockito 64 | mockito-all 65 | 1.9.5-rc1 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/JobState.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common; 2 | 3 | public enum JobState { 4 | QUEUED, 5 | WORKING, 6 | COMPLETE, 7 | UNKNOWN 8 | } -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/JobStatus.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common; 2 | 3 | public class JobStatus { 4 | private final int numerator; 5 | private final int denominator; 6 | private final JobState state; 7 | private final boolean running; 8 | private final boolean statusKnown; 9 | private final String jobHandle; 10 | 11 | public JobStatus(int numerator, 12 | int denominator, 13 | JobState state, 14 | String jobHandle) 15 | { 16 | this.state = state; 17 | this.numerator = numerator; 18 | this.denominator = denominator; 19 | this.running = this.state == JobState.WORKING; 20 | this.statusKnown = (denominator != 0); 21 | this.jobHandle = jobHandle; 22 | } 23 | 24 | public int getNumerator() { 25 | return numerator; 26 | } 27 | 28 | public int getDenominator() { 29 | return denominator; 30 | } 31 | 32 | public JobState getState() { 33 | return state; 34 | } 35 | 36 | public boolean isRunning() { 37 | return running; 38 | } 39 | 40 | public boolean isStatusKnown() { 41 | return statusKnown; 42 | } 43 | 44 | public String getJobHandle() { 45 | return jobHandle; 46 | } 47 | 48 | public String toString() { 49 | StringBuilder sb = new StringBuilder(); 50 | 51 | sb.append(jobHandle).append(": ") 52 | .append(numerator).append("/").append(denominator) 53 | .append(" - ").append(getState()) 54 | .append(" isRunning: ").append(isRunning()) 55 | .append(" statusKnown: ").append(isStatusKnown()); 56 | 57 | return sb.toString(); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/client/AbstractGearmanClient.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.client; 2 | 3 | import net.johnewart.gearman.common.JobStatus; 4 | import net.johnewart.gearman.common.events.GearmanClientEventListener; 5 | import net.johnewart.gearman.common.interfaces.GearmanClient; 6 | 7 | import java.util.HashSet; 8 | import java.util.Set; 9 | 10 | public abstract class AbstractGearmanClient implements GearmanClient { 11 | protected final Set gearmanClientEventListenerSet; 12 | 13 | protected AbstractGearmanClient() { 14 | gearmanClientEventListenerSet = new HashSet<>(); 15 | } 16 | 17 | @Override 18 | public void registerEventListener(GearmanClientEventListener listener) { 19 | gearmanClientEventListenerSet.add(listener); 20 | } 21 | 22 | protected void handleWorkData(final String jobHandle, final byte[] data) { 23 | for(GearmanClientEventListener el : gearmanClientEventListenerSet) { 24 | el.handleWorkData(jobHandle, data); 25 | } 26 | } 27 | 28 | protected void handleWorkWarning(final String jobHandle, final byte[] warning) { 29 | for(GearmanClientEventListener el : gearmanClientEventListenerSet) { 30 | el.handleWorkWarning(jobHandle, warning); 31 | } 32 | } 33 | 34 | protected void handleWorkStatus(final String jobHandle, final JobStatus jobStatus) { 35 | for(GearmanClientEventListener el : gearmanClientEventListenerSet) { 36 | el.handleWorkStatus(jobHandle, jobStatus); 37 | } 38 | } 39 | 40 | 41 | } 42 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/events/GearmanClientEventListener.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.events; 2 | 3 | import net.johnewart.gearman.common.JobStatus; 4 | 5 | public interface GearmanClientEventListener { 6 | void handleWorkData(final String jobHandle, final byte[] data); 7 | void handleWorkWarning(final String jobHandle, final byte[] warning); 8 | void handleWorkStatus(final String jobHandle, JobStatus jobStatus); 9 | } 10 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/events/WorkEvent.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.events; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.interfaces.GearmanWorker; 5 | 6 | public class WorkEvent { 7 | public final Job job; 8 | public final GearmanWorker worker; 9 | 10 | public WorkEvent(final Job job, final GearmanWorker worker) { 11 | this.job = job; 12 | this.worker = worker; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/EngineClient.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | import net.johnewart.gearman.common.JobStatus; 4 | import net.johnewart.gearman.common.packets.Packet; 5 | import net.johnewart.gearman.common.Job; 6 | 7 | /** 8 | * This interface is for implementations of the clients that are connected to the 9 | * core engine. (i.e server to client relationship) 10 | */ 11 | public interface EngineClient { 12 | Job getCurrentJob(); 13 | void setCurrentJob(final Job job); 14 | void sendWorkResults(final String jobHandle, final byte[] data); 15 | void sendWorkData(final String jobHandle, final byte[] data); 16 | void sendWorkException(final String jobHandle, final byte[] exception); 17 | void sendWorkFail(final String jobHandle); 18 | void sendWorkWarning(final String jobHandle, final byte[] warning); 19 | void sendWorkStatus(final JobStatus jobStatus); 20 | 21 | void send(Packet packet); 22 | } 23 | 24 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/EngineWorker.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | import java.util.Set; 4 | 5 | public interface EngineWorker { 6 | public Set getAbilities(); 7 | public void wakeUp(); 8 | public void markAsleep(); 9 | 10 | 11 | } 12 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/GearmanClient.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | 4 | import net.johnewart.gearman.common.JobStatus; 5 | import net.johnewart.gearman.common.events.GearmanClientEventListener; 6 | import net.johnewart.gearman.constants.JobPriority; 7 | import net.johnewart.gearman.exceptions.JobSubmissionException; 8 | import net.johnewart.gearman.exceptions.WorkException; 9 | 10 | import java.util.Date; 11 | 12 | public interface GearmanClient { 13 | String submitFutureJob(String callback, byte[] data, Date whenToRun) throws JobSubmissionException; 14 | String submitJobInBackground(String callback, byte[] data) throws JobSubmissionException; 15 | String submitJobInBackground(String callback, byte[] data, JobPriority priority) throws JobSubmissionException; 16 | byte[] submitJob(String callback, byte[] data) throws JobSubmissionException, WorkException; 17 | byte[] submitJob(String callback, byte[] data, JobPriority priority) throws JobSubmissionException, WorkException; 18 | JobStatus getStatus(String jobHandle); 19 | void registerEventListener(GearmanClientEventListener listener); 20 | void shutdown(); 21 | } 22 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/GearmanFunction.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | import net.johnewart.gearman.common.events.WorkEvent; 4 | 5 | public interface GearmanFunction { 6 | public byte[] process(WorkEvent workEvent); 7 | } 8 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/GearmanWorker.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | 5 | import java.io.IOException; 6 | 7 | /** 8 | * The client-side gearman worker interface. 9 | */ 10 | public interface GearmanWorker { 11 | void registerCallback(String method, GearmanFunction function); 12 | void doWork(); 13 | void stopWork(); 14 | void sendData(Job job, byte[] data) throws IOException; 15 | void sendStatus(Job job, int numerator, int denominator) throws IOException; 16 | void sendWarning(Job job, byte[] warning) throws IOException; 17 | } 18 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/interfaces/JobHandleFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.interfaces; 2 | 3 | public interface JobHandleFactory { 4 | public byte[] getNextJobHandle(); 5 | } 6 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/CanDo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: jewart 10 | * Date: 11/30/12 11 | * Time: 8:43 AM 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class CanDo extends RequestPacket { 15 | private AtomicReference functionName; 16 | 17 | public CanDo() 18 | { 19 | this.type = PacketType.CAN_DO; 20 | } 21 | 22 | 23 | public CanDo(String function) 24 | { 25 | this.type = PacketType.CAN_DO; 26 | this.functionName = new AtomicReference<>(function); 27 | } 28 | 29 | public CanDo(byte[] pktdata) 30 | { 31 | super(pktdata); 32 | this.functionName = new AtomicReference<>(); 33 | int pOff = 0; 34 | pOff = parseString(pOff, functionName); 35 | } 36 | 37 | public String getFunctionName() 38 | { 39 | return functionName.get(); 40 | 41 | } 42 | 43 | @Override 44 | public byte[] toByteArray() 45 | { 46 | return concatByteArrays(getHeader(), functionName.get().getBytes()); 47 | 48 | } 49 | 50 | @Override 51 | public int getPayloadSize() 52 | { 53 | return functionName.get().length(); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/CanDoTimeout.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import com.google.common.primitives.Ints; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | /** 10 | * Created with IntelliJ IDEA. 11 | * User: jewart 12 | * Date: 11/30/12 13 | * Time: 8:43 AM 14 | * To change this template use File | Settings | File Templates. 15 | */ 16 | public class CanDoTimeout extends RequestPacket { 17 | private AtomicReference functionName; 18 | private final int timeout; 19 | 20 | public CanDoTimeout() 21 | { 22 | this.type = PacketType.CAN_DO_TIMEOUT; 23 | this.timeout = 0; 24 | } 25 | 26 | 27 | public CanDoTimeout(String function, int timeout) 28 | { 29 | this.type = PacketType.CAN_DO_TIMEOUT; 30 | this.functionName = new AtomicReference<>(function); 31 | this.timeout = timeout; 32 | } 33 | 34 | public CanDoTimeout(byte[] pktdata) 35 | { 36 | super(pktdata); 37 | this.functionName = new AtomicReference<>(); 38 | int pOff = 0; 39 | pOff = parseString(pOff, functionName); 40 | byte[] timeoutbytes = Arrays.copyOfRange(rawdata, pOff, pOff+4); 41 | this.timeout = Ints.fromByteArray(timeoutbytes); 42 | } 43 | 44 | public String getFunctionName() 45 | { 46 | return functionName.get(); 47 | } 48 | 49 | @Override 50 | public byte[] toByteArray() 51 | { 52 | return concatByteArrays(getHeader(), functionName.get().getBytes(), String.valueOf(timeout).getBytes()); 53 | 54 | } 55 | 56 | @Override 57 | public int getPayloadSize() 58 | { 59 | return functionName.get().length() + 1 + String.valueOf(timeout).length(); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/CantDo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: jewart 10 | * Date: 11/30/12 11 | * Time: 8:43 AM 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | public class CantDo extends RequestPacket { 15 | private AtomicReference functionName; 16 | 17 | public CantDo() 18 | { 19 | this.type = PacketType.CANT_DO; 20 | } 21 | 22 | 23 | public CantDo(String function) 24 | { 25 | this.type = PacketType.CANT_DO; 26 | this.functionName = new AtomicReference<>(function); 27 | } 28 | 29 | public CantDo(byte[] pktdata) 30 | { 31 | super(pktdata); 32 | this.functionName = new AtomicReference<>(); 33 | int pOff = 0; 34 | pOff = parseString(pOff, functionName); 35 | } 36 | 37 | public String getFunctionName() 38 | { 39 | return functionName.get(); 40 | 41 | } 42 | 43 | @Override 44 | public byte[] toByteArray() 45 | { 46 | return concatByteArrays(getHeader(), functionName.get().getBytes()); 47 | } 48 | 49 | @Override 50 | public int getPayloadSize() 51 | { 52 | return functionName.get().length(); 53 | } 54 | } 55 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/EchoRequest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | import net.johnewart.gearman.constants.GearmanConstants; 5 | 6 | import java.util.Arrays; 7 | 8 | public class EchoRequest extends RequestPacket { 9 | 10 | private final byte[] data; 11 | 12 | public EchoRequest(String data) 13 | { 14 | byte[] dataBytes = data.getBytes(GearmanConstants.CHARSET); 15 | this.data = dataBytes.clone(); 16 | this.type = PacketType.ECHO_REQ; 17 | } 18 | 19 | public EchoRequest(byte[] pktdata) 20 | { 21 | super(pktdata); 22 | int pOff = 0; 23 | this.data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 24 | this.type = PacketType.ECHO_REQ; 25 | } 26 | 27 | @Override 28 | public byte[] toByteArray() 29 | { 30 | return concatByteArrays(getHeader(), data); 31 | } 32 | 33 | @Override 34 | public int getPayloadSize() 35 | { 36 | return data.length; 37 | } 38 | 39 | 40 | public byte[] getData() { 41 | return data; 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/GetStatus.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | /** 8 | * Created with IntelliJ IDEA. 9 | * User: jewart 10 | * Date: 11/30/12 11 | * Time: 8:48 AM 12 | * To change this template use File | Settings | File Templates. 13 | */ 14 | 15 | public class GetStatus extends RequestPacket 16 | { 17 | public AtomicReference jobHandle; 18 | 19 | public GetStatus() 20 | { } 21 | 22 | public GetStatus(String jobHandle) 23 | { 24 | this.jobHandle = new AtomicReference<>(jobHandle); 25 | this.type = PacketType.GET_STATUS; 26 | this.size = jobHandle.length(); 27 | } 28 | 29 | public GetStatus(byte[] pktdata) 30 | { 31 | super(pktdata); 32 | this.type = PacketType.GET_STATUS; 33 | 34 | jobHandle = new AtomicReference(); 35 | 36 | int pOff = 0; 37 | pOff = parseString(pOff, jobHandle); 38 | } 39 | 40 | @Override 41 | public byte[] toByteArray() 42 | { 43 | byte[] jhbytes = jobHandle.get().getBytes(); 44 | byte[] result = this.concatByteArrays(getHeader(), jhbytes); 45 | return result; 46 | } 47 | 48 | @Override 49 | public int getPayloadSize() 50 | { 51 | return this.jobHandle.get().length(); 52 | } 53 | 54 | 55 | } 56 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/GrabJob.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class GrabJob extends RequestPacket { 6 | 7 | public GrabJob() 8 | { 9 | this.type = PacketType.GRAB_JOB; 10 | } 11 | 12 | public GrabJob(byte[] pktdata) 13 | { 14 | super(pktdata); 15 | } 16 | 17 | @Override 18 | public byte[] toByteArray() 19 | { 20 | return getHeader(); 21 | } 22 | 23 | @Override 24 | public int getPayloadSize() 25 | { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/GrabJobAll.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class GrabJobAll extends RequestPacket { 6 | 7 | public GrabJobAll() 8 | { 9 | this.type = PacketType.GRAB_JOB_ALL; 10 | } 11 | 12 | public GrabJobAll(byte[] pktdata) 13 | { 14 | super(pktdata); 15 | } 16 | 17 | @Override 18 | public byte[] toByteArray() 19 | { 20 | return getHeader(); 21 | } 22 | 23 | @Override 24 | public int getPayloadSize() 25 | { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/GrabJobUniq.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class GrabJobUniq extends RequestPacket { 6 | 7 | public GrabJobUniq() 8 | { 9 | this.type = PacketType.GRAB_JOB_UNIQ; 10 | } 11 | 12 | public GrabJobUniq(byte[] pktdata) 13 | { 14 | super(pktdata); 15 | } 16 | 17 | @Override 18 | public byte[] toByteArray() 19 | { 20 | return getHeader(); 21 | } 22 | 23 | @Override 24 | public int getPayloadSize() 25 | { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/OptionRequest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | public class OptionRequest extends RequestPacket 8 | { 9 | public AtomicReference option; 10 | 11 | public OptionRequest() 12 | { } 13 | 14 | public OptionRequest(byte[] pktdata) 15 | { 16 | super(pktdata); 17 | this.type = PacketType.OPTION_REQ; 18 | 19 | option = new AtomicReference(); 20 | 21 | int pOff = 0; 22 | pOff = parseString(pOff, option); 23 | } 24 | 25 | @Override 26 | public byte[] toByteArray() 27 | { 28 | byte[] optbytes = option.get().getBytes(); 29 | byte[] result = this.concatByteArrays(getHeader(), optbytes); 30 | return result; 31 | } 32 | 33 | @Override 34 | public int getPayloadSize() 35 | { 36 | return this.option.get().length(); 37 | } 38 | 39 | public String getOption() { 40 | return option.get(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/PreSleep.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class PreSleep extends RequestPacket { 6 | 7 | public PreSleep() 8 | { 9 | this.type = PacketType.PRE_SLEEP; 10 | } 11 | 12 | public PreSleep(byte[] pktdata) 13 | { 14 | super(pktdata); 15 | } 16 | 17 | 18 | @Override 19 | public byte[] toByteArray() 20 | { 21 | return getHeader(); 22 | } 23 | 24 | @Override 25 | public int getPayloadSize() 26 | { 27 | return 0; 28 | } 29 | } 30 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/RequestPacket.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.common.packets.Packet; 4 | import net.johnewart.gearman.constants.PacketMagic; 5 | 6 | public abstract class RequestPacket extends Packet { 7 | public RequestPacket () 8 | { 9 | } 10 | 11 | public RequestPacket(byte[] fromdata) 12 | { 13 | super(fromdata); 14 | } 15 | 16 | @Override 17 | public byte[] getMagic() 18 | { 19 | return PacketMagic.REQUEST; 20 | } 21 | 22 | 23 | } 24 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/ResetAbilities.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class ResetAbilities extends RequestPacket { 6 | 7 | public ResetAbilities() 8 | { 9 | this.type = PacketType.RESET_ABILITIES; 10 | } 11 | 12 | public ResetAbilities(byte[] pktdata) 13 | { 14 | super(pktdata); 15 | } 16 | 17 | @Override 18 | public byte[] toByteArray() 19 | { 20 | return getHeader(); 21 | } 22 | 23 | @Override 24 | public int getPayloadSize() 25 | { 26 | return 0; 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/request/SetClientId.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.request; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.UUID; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | public class SetClientId extends RequestPacket { 9 | private AtomicReference clientId; 10 | 11 | /** 12 | * Create a SET_CLIENT_ID packet with a random ID 13 | */ 14 | public SetClientId() 15 | { 16 | this(UUID.randomUUID().toString()); 17 | } 18 | 19 | public SetClientId(String clientId) 20 | { 21 | this.type = PacketType.SET_CLIENT_ID; 22 | this.clientId = new AtomicReference<>(clientId); 23 | } 24 | 25 | public SetClientId(byte[] pktdata) 26 | { 27 | super(pktdata); 28 | this.clientId = new AtomicReference<>(); 29 | int pOff = 0; 30 | parseString(pOff, clientId); 31 | } 32 | 33 | public String getClientId() 34 | { 35 | return clientId.get(); 36 | } 37 | 38 | @Override 39 | public byte[] toByteArray() 40 | { 41 | return concatByteArrays(getHeader(), clientId.get().getBytes()); 42 | } 43 | 44 | @Override 45 | public int getPayloadSize() 46 | { 47 | return clientId.get().length(); 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/EchoResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.packets.request.EchoRequest; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | 8 | 9 | public class EchoResponse extends ResponsePacket { 10 | 11 | private final byte[] data; 12 | 13 | public EchoResponse(EchoRequest echoRequest) 14 | { 15 | this.type = PacketType.ECHO_RES; 16 | this.data = echoRequest.getData().clone(); 17 | } 18 | 19 | public EchoResponse(byte[] pktdata) 20 | { 21 | super(pktdata); 22 | int pOff = 0; 23 | this.data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 24 | this.type = PacketType.ECHO_RES; 25 | } 26 | 27 | @Override 28 | public byte[] toByteArray() 29 | { 30 | byte[] result = concatByteArrays(getHeader(), data); 31 | return result; 32 | } 33 | 34 | @Override 35 | public int getPayloadSize() 36 | { 37 | return data.length; 38 | } 39 | 40 | 41 | public byte[] getData() { 42 | return data; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/JobAssign.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | public class JobAssign extends ResponsePacket { 10 | protected AtomicReference jobHandle, functionName; 11 | protected byte[] data; 12 | 13 | public JobAssign(byte[] pktdata) 14 | { 15 | super(pktdata); 16 | jobHandle = new AtomicReference<>(); 17 | functionName = new AtomicReference<>(); 18 | int pOff = parseString(0, jobHandle); 19 | pOff = parseString(pOff, functionName); 20 | this.data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 21 | this.type = PacketType.JOB_ASSIGN; 22 | } 23 | 24 | public JobAssign(String jobhandle, String functionName, byte[] data) 25 | { 26 | this.jobHandle = new AtomicReference<>(jobhandle); 27 | this.functionName = new AtomicReference<>(functionName); 28 | this.data = data.clone(); 29 | this.type = PacketType.JOB_ASSIGN; 30 | } 31 | 32 | public String getJobHandle() 33 | { 34 | return this.jobHandle.get(); 35 | } 36 | 37 | @Override 38 | public byte[] toByteArray() 39 | { 40 | byte[] metadata = stringsToTerminatedByteArray(jobHandle.get(), functionName.get()); 41 | return concatByteArrays(getHeader(), metadata, this.data); 42 | } 43 | 44 | @Override 45 | public int getPayloadSize() 46 | { 47 | return this.jobHandle.get().length() + 1 + 48 | this.functionName.get().length() + 1 + 49 | this.data.length; 50 | } 51 | 52 | public String getFunctionName() { 53 | return functionName.get(); 54 | } 55 | 56 | public byte[] getData() { 57 | return data; 58 | } 59 | 60 | public Job getJob() { 61 | return new Job.Builder() 62 | .jobHandle(this.jobHandle.get()) 63 | .data(this.data) 64 | .functionName(this.functionName.get()) 65 | .build(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/JobAssignAll.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | public class JobAssignAll extends ResponsePacket { 10 | protected AtomicReference jobHandle, functionName; 11 | protected byte[] data; 12 | 13 | public JobAssignAll(byte[] pktdata) 14 | { 15 | super(pktdata); 16 | jobHandle = new AtomicReference<>(); 17 | functionName = new AtomicReference<>(); 18 | int pOff = parseString(0, jobHandle); 19 | pOff = parseString(pOff, functionName); 20 | this.data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 21 | this.type = PacketType.JOB_ASSIGN_ALL; 22 | } 23 | 24 | public JobAssignAll(String jobhandle, String functionName, byte[] data) 25 | { 26 | this.jobHandle = new AtomicReference<>(jobhandle); 27 | this.functionName = new AtomicReference<>(functionName); 28 | this.data = data.clone(); 29 | this.type = PacketType.JOB_ASSIGN; 30 | } 31 | 32 | public String getJobHandle() 33 | { 34 | return this.jobHandle.get(); 35 | } 36 | 37 | @Override 38 | public byte[] toByteArray() 39 | { 40 | byte[] metadata = stringsToTerminatedByteArray(jobHandle.get(), functionName.get()); 41 | return concatByteArrays(getHeader(), metadata, this.data); 42 | } 43 | 44 | @Override 45 | public int getPayloadSize() 46 | { 47 | return this.jobHandle.get().length() + 1 + 48 | this.functionName.get().length() + 1 + 49 | this.data.length; 50 | } 51 | 52 | public String getFunctionName() { 53 | return functionName.get(); 54 | } 55 | 56 | public byte[] getData() { 57 | return data; 58 | } 59 | 60 | public Job getJob() { 61 | return new Job.Builder() 62 | .jobHandle(this.jobHandle.get()) 63 | .data(this.data) 64 | .functionName(this.functionName.get()) 65 | .build(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/JobAssignUniq.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | // TODO: Refactor this class so that there's not so much repeated between this and JobAssign. 10 | public class JobAssignUniq extends ResponsePacket { 11 | private AtomicReference jobHandle, functionName, uniqueId; 12 | private byte[] data; 13 | 14 | public JobAssignUniq(byte[] pktdata) 15 | { 16 | super(pktdata); 17 | jobHandle = new AtomicReference<>(); 18 | functionName = new AtomicReference<>(); 19 | uniqueId = new AtomicReference<>(); 20 | int pOff = parseString(0, jobHandle); 21 | pOff = parseString(pOff, functionName); 22 | pOff = parseString(pOff, uniqueId); 23 | this.data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 24 | this.type = PacketType.JOB_ASSIGN_UNIQ; 25 | } 26 | 27 | public JobAssignUniq(String jobhandle, String functionName, String uniqueId, byte[] data) 28 | { 29 | this.jobHandle = new AtomicReference<>(jobhandle); 30 | this.functionName = new AtomicReference<>(functionName); 31 | this.uniqueId = new AtomicReference<>(uniqueId); 32 | this.data = data.clone(); 33 | this.type = PacketType.JOB_ASSIGN_UNIQ; 34 | } 35 | 36 | public String getJobHandle() 37 | { 38 | return this.jobHandle.get(); 39 | } 40 | 41 | @Override 42 | public byte[] toByteArray() 43 | { 44 | byte[] metadata = stringsToTerminatedByteArray(jobHandle.get(), functionName.get(), uniqueId.get()); 45 | return concatByteArrays(getHeader(), metadata, data); 46 | } 47 | 48 | @Override 49 | public int getPayloadSize() 50 | { 51 | return this.jobHandle.get().length() + 1 + 52 | this.functionName.get().length() + 1 + 53 | this.uniqueId.get().length() + 1 + 54 | this.data.length; 55 | } 56 | 57 | public String getFunctionName() { 58 | return functionName.get(); 59 | } 60 | 61 | public String getUniqueId() { 62 | return uniqueId.get(); 63 | } 64 | 65 | public byte[] getData() { 66 | return data; 67 | } 68 | 69 | public Job getJob() { 70 | return new Job.Builder() 71 | .jobHandle(this.jobHandle.get()) 72 | .data(this.data) 73 | .functionName(this.functionName.get()) 74 | .uniqueID(this.uniqueId.get()) 75 | .build(); 76 | } 77 | } 78 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/JobCreated.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | public class JobCreated extends ResponsePacket { 8 | public AtomicReference jobHandle; 9 | 10 | public JobCreated(byte[] pktdata) 11 | { 12 | super(pktdata); 13 | jobHandle = new AtomicReference<>(); 14 | parseString(0, jobHandle); 15 | this.type = PacketType.JOB_CREATED; 16 | } 17 | 18 | public JobCreated(String jobhandle) 19 | { 20 | jobHandle = new AtomicReference<>(jobhandle); 21 | this.type = PacketType.JOB_CREATED; 22 | } 23 | 24 | public String getJobHandle() 25 | { 26 | return this.jobHandle.get(); 27 | } 28 | 29 | @Override 30 | public byte[] toByteArray() 31 | { 32 | return concatByteArrays(getHeader(), jobHandle.get().getBytes()); 33 | } 34 | 35 | @Override 36 | public int getPayloadSize() 37 | { 38 | return this.jobHandle.get().length(); 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/NoJob.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public class NoJob extends ResponsePacket { 6 | 7 | public NoJob() 8 | { 9 | this.type = PacketType.NO_JOB; 10 | } 11 | 12 | @Override 13 | public byte[] toByteArray() 14 | { 15 | return getHeader(); 16 | } 17 | 18 | @Override 19 | public int getPayloadSize() 20 | { 21 | return 0; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/NoOp.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: jewart 8 | * Date: 11/30/12 9 | * Time: 8:43 AM 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public class NoOp extends ResponsePacket { 13 | 14 | public NoOp() 15 | { 16 | this.type = PacketType.NOOP; 17 | } 18 | 19 | @Override 20 | public byte[] toByteArray() 21 | { 22 | return getHeader(); 23 | } 24 | 25 | @Override 26 | public int getPayloadSize() 27 | { 28 | return 0; 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/OptionResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.packets.request.EchoRequest; 4 | import net.johnewart.gearman.constants.PacketType; 5 | 6 | import java.util.Arrays; 7 | 8 | 9 | public class OptionResponse extends ResponsePacket { 10 | 11 | private final byte[] data; 12 | 13 | public OptionResponse(String option) 14 | { 15 | this.type = PacketType.OPTION_RES; 16 | this.data = option.getBytes(); 17 | } 18 | 19 | @Override 20 | public byte[] toByteArray() 21 | { 22 | byte[] result = concatByteArrays(getHeader(), data); 23 | return result; 24 | } 25 | 26 | @Override 27 | public int getPayloadSize() 28 | { 29 | return data.length; 30 | } 31 | 32 | 33 | public byte[] getData() { 34 | return data; 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/ResponsePacket.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.packets.Packet; 4 | import net.johnewart.gearman.constants.PacketMagic; 5 | 6 | public abstract class ResponsePacket extends Packet { 7 | public ResponsePacket() 8 | { 9 | } 10 | 11 | public ResponsePacket(byte[] fromdata) 12 | { 13 | super(fromdata); 14 | } 15 | 16 | public byte[] getMagic() 17 | { 18 | return PacketMagic.RESPONSE; 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkCompleteResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: jewart 8 | * Date: 11/30/12 9 | * Time: 10:12 AM 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public class WorkCompleteResponse extends WorkDataResponse { 13 | public WorkCompleteResponse(String jobhandle, byte[] data) 14 | { 15 | super(jobhandle, data); 16 | this.type = PacketType.WORK_COMPLETE; 17 | } 18 | 19 | public WorkCompleteResponse(byte[] pktdata) 20 | { 21 | super(pktdata); 22 | 23 | this.type = PacketType.WORK_COMPLETE; 24 | } 25 | } -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkDataResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.Arrays; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | public class WorkDataResponse extends ResponsePacket implements WorkResponse { 9 | 10 | public AtomicReference jobHandle; 11 | public byte[] data; 12 | 13 | public WorkDataResponse(String jobhandle, byte[] data) 14 | { 15 | this.jobHandle = new AtomicReference<>(jobhandle); 16 | this.data = data.clone(); 17 | this.type = PacketType.WORK_DATA; 18 | } 19 | 20 | public WorkDataResponse(byte[] pktdata) 21 | { 22 | super(pktdata); 23 | this.jobHandle = new AtomicReference<>(); 24 | 25 | int pOff = 0; 26 | pOff = parseString(pOff, jobHandle); 27 | data = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 28 | 29 | } 30 | 31 | @Override 32 | public byte[] toByteArray() 33 | { 34 | byte[] metadata = stringsToTerminatedByteArray(jobHandle.get()); 35 | return concatByteArrays(getHeader(), metadata, data); 36 | } 37 | 38 | public String getJobHandle() { 39 | return jobHandle.get(); 40 | } 41 | 42 | public int getPayloadSize() 43 | { 44 | return this.jobHandle.get().length() + 1 + 45 | this.data.length; 46 | } 47 | 48 | public byte[] getData() 49 | { 50 | return data; 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkExceptionResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.Arrays; 6 | import java.util.concurrent.atomic.AtomicReference; 7 | 8 | public class WorkExceptionResponse extends ResponsePacket implements WorkResponse 9 | { 10 | public AtomicReference jobHandle; 11 | public byte[] exception; 12 | 13 | public WorkExceptionResponse(String jobhandle, byte[] exception) 14 | { 15 | this.jobHandle = new AtomicReference(jobhandle); 16 | this.exception = exception.clone(); 17 | this.type = PacketType.WORK_EXCEPTION; 18 | } 19 | 20 | public WorkExceptionResponse(byte[] pktdata) 21 | { 22 | super(pktdata); 23 | this.jobHandle = new AtomicReference(); 24 | int pOff = 0; 25 | pOff = parseString(pOff, jobHandle); 26 | exception = Arrays.copyOfRange(rawdata, pOff, rawdata.length); 27 | } 28 | 29 | public byte[] toByteArray() 30 | { 31 | byte[] metadata = stringsToTerminatedByteArray(jobHandle.get()); 32 | return concatByteArrays(getHeader(), metadata, exception); 33 | } 34 | 35 | @Override 36 | public int getPayloadSize() 37 | { 38 | return this.jobHandle.get().length() + 1 + 39 | this.exception.length; 40 | } 41 | 42 | @Override 43 | public String getJobHandle() 44 | { 45 | return this.jobHandle.get(); 46 | } 47 | 48 | public byte[] getException() { 49 | return exception; 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkFailResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | import java.util.concurrent.atomic.AtomicReference; 6 | 7 | public class WorkFailResponse extends ResponsePacket implements WorkResponse { 8 | public AtomicReference jobHandle; 9 | 10 | public WorkFailResponse(String jobhandle) 11 | { 12 | this.jobHandle = new AtomicReference(jobhandle); 13 | this.type = PacketType.WORK_FAIL; 14 | } 15 | 16 | public WorkFailResponse(byte[] pktdata) 17 | { 18 | super(pktdata); 19 | this.jobHandle = new AtomicReference(); 20 | int pOff = 0; 21 | parseString(0, jobHandle); 22 | } 23 | 24 | @Override 25 | public byte[] toByteArray() 26 | { 27 | return concatByteArrays(getHeader(), jobHandle.get().getBytes()); 28 | } 29 | 30 | @Override 31 | public int getPayloadSize() 32 | { 33 | return this.jobHandle.get().length(); 34 | } 35 | 36 | @Override 37 | public String getJobHandle() 38 | { 39 | return this.jobHandle.get(); 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | public interface WorkResponse { 6 | public abstract String getJobHandle(); 7 | public abstract PacketType getType(); 8 | } 9 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkStatus.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.common.JobState; 4 | import net.johnewart.gearman.common.JobStatus; 5 | import net.johnewart.gearman.constants.PacketType; 6 | 7 | import java.util.concurrent.atomic.AtomicReference; 8 | 9 | 10 | public class WorkStatus extends ResponsePacket 11 | { 12 | private AtomicReference jobHandle; 13 | private int completenumerator; 14 | private int completedenominator; 15 | 16 | public WorkStatus() 17 | { } 18 | 19 | public WorkStatus(String jobhandle, int numerator, int denominator) 20 | { 21 | this.jobHandle = new AtomicReference(jobhandle); 22 | this.completenumerator = numerator; 23 | this.completedenominator = denominator; 24 | this.type = PacketType.WORK_STATUS; 25 | } 26 | 27 | public WorkStatus(JobStatus jobStatus) 28 | { 29 | this.jobHandle = new AtomicReference<>(jobStatus.getJobHandle()); 30 | this.completedenominator = jobStatus.getDenominator(); 31 | this.completenumerator = jobStatus.getNumerator(); 32 | this.type = PacketType.WORK_STATUS; 33 | } 34 | 35 | public WorkStatus(byte[] pktdata) 36 | { 37 | super(pktdata); 38 | jobHandle = new AtomicReference(); 39 | AtomicReference numerator = new AtomicReference(); 40 | AtomicReference denominator = new AtomicReference(); 41 | 42 | int pOff = 0; 43 | pOff = parseString(pOff, jobHandle); 44 | pOff = parseString(pOff, numerator); 45 | pOff = parseString(pOff, denominator); 46 | 47 | try { 48 | completedenominator = Integer.valueOf(denominator.get()); 49 | } catch (NumberFormatException nfe) { 50 | completedenominator = -1; 51 | } 52 | 53 | try { 54 | completenumerator = Integer.valueOf(numerator.get()); 55 | } catch (NumberFormatException nfe) { 56 | completenumerator = -1; 57 | } 58 | } 59 | 60 | @Override 61 | public byte[] toByteArray() 62 | { 63 | byte[] metadata = stringsToTerminatedByteArray(false, jobHandle.get(), String.valueOf(completenumerator), String.valueOf(completedenominator)); 64 | return concatByteArrays(getHeader(), metadata); 65 | } 66 | 67 | @Override 68 | public int getPayloadSize() 69 | { 70 | return this.jobHandle.get().length() + 1 + 71 | String.valueOf(completenumerator).length() + 1 + 72 | String.valueOf(completedenominator).length(); 73 | } 74 | 75 | public String getJobHandle() { 76 | return jobHandle.get(); 77 | } 78 | 79 | public int getCompleteNumerator() { 80 | return completenumerator; 81 | } 82 | 83 | public int getCompleteDenominator() { 84 | return completedenominator; 85 | } 86 | 87 | public JobStatus toJobStatus() { 88 | return new JobStatus( 89 | completenumerator, 90 | completedenominator, 91 | JobState.WORKING, 92 | getJobHandle() 93 | ); 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/common/packets/response/WorkWarningResponse.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.packets.response; 2 | 3 | import net.johnewart.gearman.constants.PacketType; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: jewart 8 | * Date: 11/30/12 9 | * Time: 10:14 AM 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public class WorkWarningResponse extends WorkDataResponse 13 | { 14 | public WorkWarningResponse(String jobhandle, byte[] data) 15 | { 16 | super(jobhandle, data); 17 | this.type = PacketType.WORK_WARNING; 18 | } 19 | 20 | public WorkWarningResponse(byte[] pktdata) 21 | { 22 | super(pktdata); 23 | this.type = PacketType.WORK_WARNING; 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/constants/GearmanConstants.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012, Isaiah van der Elst (isaiah.v@comcast.net) 3 | * All rights reserved. 4 | * 5 | * Redistribution and use in source and binary forms, with or without 6 | * modification, are permitted provided that the following conditions are met: 7 | * 8 | * - Redistributions of source code must retain the above copyright notice, 9 | * this list of conditions and the following disclaimer. 10 | * 11 | * - Redistributions in binary form must reproduce the above copyright notice, 12 | * this list of conditions and the following disclaimer in the documentation 13 | * and/or other materials provided with the distribution. 14 | * 15 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 16 | * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 | * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 | * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 19 | * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 20 | * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 21 | * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 22 | * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 23 | * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 24 | * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 25 | * POSSIBILITY OF SUCH DAMAGE. 26 | */ 27 | 28 | package net.johnewart.gearman.constants; 29 | 30 | import java.nio.charset.Charset; 31 | 32 | public class GearmanConstants { 33 | 34 | public static final String PROJECT_NAME = "@project.name@"; 35 | public static final String VERSION = "@project.version@"; 36 | 37 | private static final String CHARSET_NAME = "UTF-8"; 38 | public static final Charset CHARSET; 39 | public static final int THREAD_TIMEOUT; 40 | 41 | static { 42 | CHARSET = Charset.forName(CHARSET_NAME); 43 | THREAD_TIMEOUT = 1000; 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/constants/JobPriority.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.constants; 2 | 3 | public enum JobPriority { 4 | HIGH, 5 | NORMAL, 6 | LOW; 7 | 8 | public int getIndex() { return ordinal() + 1; } 9 | 10 | public static JobPriority fromInteger(int x) { 11 | switch(x) { 12 | case 1: return HIGH; 13 | case 2: return NORMAL; 14 | case 3: return LOW; 15 | } 16 | return null; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/constants/PacketMagic.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.constants; 2 | 3 | public class PacketMagic { 4 | public static byte[] REQUEST = {0, 'R', 'E', 'Q'}; 5 | public static byte[] RESPONSE = {0, 'R', 'E', 'S'}; 6 | } 7 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/exceptions/JobSubmissionException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.exceptions; 2 | 3 | public class JobSubmissionException extends Throwable { 4 | } 5 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/exceptions/NoServersAvailableException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.exceptions; 2 | 3 | public class NoServersAvailableException extends JobSubmissionException { 4 | } 5 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/exceptions/WorkException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.exceptions; 2 | 3 | public class WorkException extends Throwable { 4 | protected String jobHandle; 5 | 6 | public String getJobHandle() { 7 | return jobHandle; 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/exceptions/WorkExceptionException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.exceptions; 2 | 3 | public class WorkExceptionException extends WorkException { 4 | private String message; 5 | 6 | public WorkExceptionException(final String jobHandle, final byte[] exceptionData) { 7 | this.jobHandle = jobHandle; 8 | this.message = new String(exceptionData); 9 | } 10 | 11 | public String getMessage() { 12 | return message; 13 | } 14 | } 15 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/exceptions/WorkFailException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.exceptions; 2 | 3 | public class WorkFailException extends WorkException { 4 | public WorkFailException(final String jobHandle) { 5 | this.jobHandle = jobHandle; 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gearman-common/src/main/java/net/johnewart/gearman/net/ConnectionFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.net; 2 | 3 | public class ConnectionFactory { 4 | 5 | final String host; 6 | final int port; 7 | 8 | public ConnectionFactory(String host, int port) { 9 | this.host = host; 10 | this.port = port; 11 | } 12 | 13 | public Connection build() { 14 | return new Connection(host, port); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /gearman-common/src/test/java/net/johnewart/gearman/common/net/ConnectionPoolTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.common.net; 2 | 3 | import net.johnewart.gearman.common.packets.request.EchoRequest; 4 | import net.johnewart.gearman.common.packets.response.EchoResponse; 5 | import net.johnewart.gearman.exceptions.NoServersAvailableException; 6 | import net.johnewart.gearman.net.Connection; 7 | import net.johnewart.gearman.net.ConnectionPool; 8 | import org.junit.Test; 9 | 10 | import java.io.IOException; 11 | 12 | import static junit.framework.Assert.*; 13 | import static org.mockito.Matchers.any; 14 | import static org.mockito.Mockito.*; 15 | 16 | public class ConnectionPoolTest { 17 | @Test 18 | public void testReEstablishingConnectionsWorks() { 19 | 20 | Connection connection1 = mock(Connection.class); 21 | Connection connection2 = mock(Connection.class); 22 | 23 | ConnectionPool connectionPool = new ConnectionPool(); 24 | connectionPool.addConnection(connection1); 25 | connectionPool.addConnection(connection2); 26 | 27 | try { 28 | connectionPool.getConnection(); 29 | } catch (NoServersAvailableException nsae) { 30 | assertNotNull(nsae); 31 | } 32 | 33 | try { 34 | // Simulate server coming back 35 | final EchoResponse echoResponse = new EchoResponse(new EchoRequest("ok")); 36 | when(connection1.isHealthy()).thenReturn(true); 37 | when(connection1.getNextPacket()).thenReturn(echoResponse); 38 | Connection c = connectionPool.getConnection(); 39 | assertEquals(c, connection1); 40 | } catch (NoServersAvailableException nsae) { 41 | fail(); 42 | } catch (IOException ioe) { 43 | fail(); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gearman-embedded-server/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | gearman-java 7 | net.johnewart.gearman 8 | 0.8.11-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | gearman-embedded-server 13 | 14 | 15 | 16 | net.johnewart.gearman 17 | gearman-common 18 | ${project.version} 19 | 20 | 21 | net.johnewart.gearman 22 | gearman-engine 23 | ${project.version} 24 | 25 | 26 | -------------------------------------------------------------------------------- /gearman-embedded-server/src/main/java/net/johnewart/gearman/embedded/EmbeddedGearmanServer.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.embedded; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.common.Job; 5 | import net.johnewart.gearman.common.interfaces.EngineClient; 6 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 7 | import net.johnewart.gearman.engine.core.JobManager; 8 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 9 | import net.johnewart.gearman.engine.exceptions.EnqueueException; 10 | import net.johnewart.gearman.engine.metrics.MetricsEngine; 11 | import net.johnewart.gearman.engine.metrics.QueueMetrics; 12 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 13 | import net.johnewart.gearman.engine.queue.factories.MemoryJobQueueFactory; 14 | import net.johnewart.gearman.engine.storage.ExceptionStorageEngine; 15 | import net.johnewart.gearman.engine.storage.NoopExceptionStorageEngine; 16 | import net.johnewart.gearman.engine.util.LocalJobHandleFactory; 17 | import net.johnewart.gearman.engine.util.LocalUniqueIdFactory; 18 | import org.slf4j.Logger; 19 | import org.slf4j.LoggerFactory; 20 | 21 | public class EmbeddedGearmanServer { 22 | private final Logger LOG = LoggerFactory.getLogger(EmbeddedGearmanServer.class); 23 | 24 | final JobManager jobManager; 25 | final JobHandleFactory jobHandleFactory; 26 | final UniqueIdFactory uniqueIdFactory; 27 | final QueueMetrics queueMetrics; 28 | 29 | public EmbeddedGearmanServer() { 30 | MetricRegistry registry = new MetricRegistry(); 31 | JobQueueFactory jobQueueFactory = new MemoryJobQueueFactory(registry); 32 | jobHandleFactory = new LocalJobHandleFactory("embedded"); 33 | uniqueIdFactory = new LocalUniqueIdFactory(); 34 | ExceptionStorageEngine exceptionStore = new NoopExceptionStorageEngine(); 35 | queueMetrics = new MetricsEngine(registry); 36 | jobManager = new JobManager(jobQueueFactory, jobHandleFactory, uniqueIdFactory, exceptionStore, queueMetrics); 37 | } 38 | 39 | public Job submitJob(final Job job, final EngineClient client) throws EnqueueException 40 | { 41 | LOG.debug("Submitting job for client..."); 42 | return jobManager.storeJobForClient(job, client); 43 | } 44 | 45 | public Job getNextJobForWorker(final EmbeddedGearmanWorker worker) { 46 | return jobManager.nextJobForWorker(worker); 47 | } 48 | 49 | public void markWorkerAsleep(final EmbeddedGearmanWorker worker) { 50 | jobManager.markWorkerAsAsleep(worker); 51 | } 52 | 53 | public void registerWorkerAbility(final EmbeddedGearmanWorker worker, 54 | final String callback) { 55 | jobManager.registerWorkerAbility(callback, worker); 56 | } 57 | 58 | public void completeWork(final Job job, final byte[] results) { 59 | jobManager.handleWorkCompletion(job, results); 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/JobAction.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | public enum JobAction { 4 | REENQUEUE, MARKCOMPLETE, DONOTHING 5 | } 6 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/JobPool.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.interfaces.EngineClient; 5 | 6 | import java.util.Set; 7 | 8 | /** 9 | * Pool of currently running work 10 | */ 11 | public interface JobPool { 12 | void addJob(Job job); 13 | 14 | void addClientForUniqueId(String uniqueId, EngineClient client); 15 | void removeClientForUniqueId(String uniqueId, EngineClient client); 16 | Set clientsForUniqueId(String uniqueId); 17 | 18 | Job getJobByJobHandle(String jobHandle); 19 | Job getJobByUniqueId(String uniqueId); 20 | 21 | } 22 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/LocalJobPool.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.interfaces.EngineClient; 5 | import org.eclipse.jetty.util.ConcurrentHashSet; 6 | 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | public class LocalJobPool implements JobPool { 11 | private Map> uniqueIdClients; 12 | 13 | @Override 14 | public void addJob(Job job) { 15 | //To change body of implemented methods use File | Settings | File Templates. 16 | } 17 | 18 | @Override 19 | public void addClientForUniqueId(String uniqueId, EngineClient client) { 20 | clientsForUniqueId(uniqueId).add(client); 21 | } 22 | 23 | @Override 24 | public Set clientsForUniqueId(String uniqueId) { 25 | if(uniqueIdClients.containsKey(uniqueId)) 26 | return uniqueIdClients.get(uniqueId); 27 | else { 28 | Set clients = new ConcurrentHashSet<>(); 29 | uniqueIdClients.put(uniqueId, clients); 30 | return clients; 31 | } 32 | } 33 | 34 | @Override 35 | public Job getJobByJobHandle(String jobHandle) { 36 | return null; //To change body of implemented methods use File | Settings | File Templates. 37 | } 38 | 39 | @Override 40 | public Job getJobByUniqueId(String uniqueId) { 41 | return null; //To change body of implemented methods use File | Settings | File Templates. 42 | } 43 | 44 | @Override 45 | public void removeClientForUniqueId(String uniqueId, EngineClient client) { 46 | clientsForUniqueId(uniqueId).remove(client); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/QueuedJob.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | import net.johnewart.gearman.constants.JobPriority; 4 | import net.johnewart.gearman.common.Job; 5 | 6 | public final class QueuedJob implements Comparable 7 | { 8 | public final String uniqueID; 9 | public final Long timeToRun; 10 | public final JobPriority priority; 11 | public final String functionName; 12 | 13 | public QueuedJob(String uniqueID, long timeToRun, JobPriority priority, String functionName) 14 | { 15 | this.uniqueID = uniqueID; 16 | this.timeToRun = timeToRun; 17 | this.priority = priority; 18 | this.functionName = functionName; 19 | } 20 | 21 | public QueuedJob(Job job) 22 | { 23 | this.uniqueID = job.getUniqueID(); 24 | this.timeToRun = job.getTimeToRun(); 25 | this.priority = job.getPriority(); 26 | this.functionName = job.getFunctionName(); 27 | } 28 | 29 | public String getUniqueID() { 30 | return uniqueID; 31 | } 32 | 33 | public Long getTimeToRun() { 34 | return timeToRun; 35 | } 36 | 37 | public JobPriority getPriority() { 38 | return priority; 39 | } 40 | 41 | public String getFunctionName() { 42 | return functionName; 43 | } 44 | 45 | @Override 46 | public boolean equals(Object o) { 47 | if (this == o) return true; 48 | if (o == null || getClass() != o.getClass()) return false; 49 | 50 | QueuedJob that = (QueuedJob) o; 51 | 52 | if (functionName != null ? !functionName.equals(that.functionName) : that.functionName != null) return false; 53 | if (priority != that.priority) return false; 54 | if (timeToRun != null ? !timeToRun.equals(that.timeToRun) : that.timeToRun != null) return false; 55 | if (uniqueID != null ? !uniqueID.equals(that.uniqueID) : that.uniqueID != null) return false; 56 | 57 | return true; 58 | } 59 | 60 | @Override 61 | public int hashCode() { 62 | int result = uniqueID != null ? uniqueID.hashCode() : 0; 63 | result = 31 * result + (timeToRun != null ? timeToRun.hashCode() : 0); 64 | result = 31 * result + (priority != null ? priority.hashCode() : 0); 65 | result = 31 * result + (functionName != null ? functionName.hashCode() : 0); 66 | return result; 67 | } 68 | 69 | @Override 70 | public int compareTo(QueuedJob other) { 71 | return other.getTimeToRun().compareTo(this.getTimeToRun()); 72 | } 73 | } -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/UniqueIdFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | public interface UniqueIdFactory { 4 | public String generateUniqueId(); 5 | } 6 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/core/WorkerPool.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.core; 2 | 3 | import net.johnewart.gearman.common.interfaces.EngineWorker; 4 | import org.eclipse.jetty.util.ConcurrentHashSet; 5 | 6 | import java.util.concurrent.atomic.AtomicLong; 7 | 8 | public class WorkerPool { 9 | private final ConcurrentHashSet sleepingWorkers; 10 | private final ConcurrentHashSet connectedWorkers; 11 | private final AtomicLong numberOfConnectedWorkers; 12 | 13 | public WorkerPool(final String name) { 14 | sleepingWorkers = new ConcurrentHashSet<>(); 15 | connectedWorkers = new ConcurrentHashSet<>(); 16 | numberOfConnectedWorkers = new AtomicLong(0); 17 | } 18 | 19 | public void addWorker(final EngineWorker worker) { 20 | connectedWorkers.add(worker); 21 | numberOfConnectedWorkers.incrementAndGet(); 22 | } 23 | 24 | public void removeWorker(final EngineWorker worker) { 25 | sleepingWorkers.remove(worker); 26 | connectedWorkers.remove(worker); 27 | numberOfConnectedWorkers.decrementAndGet(); 28 | } 29 | 30 | public void markSleeping(final EngineWorker worker) { 31 | sleepingWorkers.add(worker); 32 | worker.markAsleep(); 33 | } 34 | 35 | public void wakeupWorkers() { 36 | for (final EngineWorker w : sleepingWorkers) { 37 | w.wakeUp(); 38 | } 39 | } 40 | 41 | public void markAwake(final EngineWorker worker) { 42 | sleepingWorkers.remove(worker); 43 | } 44 | 45 | public long getNumberOfConnectedWorkers() { 46 | return numberOfConnectedWorkers.longValue(); 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/exceptions/EnqueueException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.exceptions; 2 | 3 | public class EnqueueException extends Exception 4 | { 5 | private final Exception inner; 6 | private final String message; 7 | 8 | public EnqueueException(Exception inner) 9 | { 10 | this.inner = inner; 11 | this.message = inner.getMessage(); 12 | } 13 | 14 | @Override 15 | public String getMessage() 16 | { 17 | return message; 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/exceptions/IllegalJobStateTransitionException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.exceptions; 2 | 3 | public class IllegalJobStateTransitionException extends Exception { 4 | String message; 5 | 6 | public IllegalJobStateTransitionException(String message) 7 | { 8 | this.message = message; 9 | } 10 | 11 | public String toString() 12 | { 13 | return "IllegalJobStateTransitionException: " + message; 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/exceptions/JobQueueFactoryException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.exceptions; 2 | 3 | public class JobQueueFactoryException extends Exception { 4 | public JobQueueFactoryException(String message) { 5 | super(message); 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/exceptions/PersistenceException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.exceptions; 2 | 3 | public class PersistenceException extends Exception 4 | { 5 | private final String message; 6 | 7 | public PersistenceException(String message) 8 | { 9 | this.message = message; 10 | } 11 | 12 | @Override 13 | public String getMessage() 14 | { 15 | return message; 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/exceptions/QueueFullException.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.exceptions; 2 | 3 | public class QueueFullException extends Exception 4 | { 5 | public QueueFullException() 6 | { 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/healthchecks/RedisHealthCheck.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.healthchecks; 2 | 3 | import com.codahale.metrics.health.HealthCheck; 4 | import redis.clients.jedis.Jedis; 5 | 6 | public class RedisHealthCheck extends HealthCheck 7 | { 8 | private final Jedis redisClient; 9 | 10 | public RedisHealthCheck(Jedis redisClient) 11 | { 12 | this.redisClient = redisClient; 13 | } 14 | 15 | @Override 16 | public Result check() throws Exception 17 | { 18 | try 19 | { 20 | redisClient.connect(); 21 | 22 | if (redisClient.isConnected()) 23 | { 24 | return Result.healthy(); 25 | } 26 | else 27 | { 28 | return Result.unhealthy("Cannot connect to " + redisClient.toString()); 29 | } 30 | } 31 | finally 32 | { 33 | redisClient.disconnect(); 34 | } 35 | } 36 | } 37 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/metrics/QueueMetrics.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.metrics; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import net.johnewart.gearman.common.Job; 5 | import net.johnewart.gearman.common.interfaces.EngineWorker; 6 | import net.johnewart.gearman.engine.queue.JobQueue; 7 | import org.joda.time.DateTime; 8 | 9 | public interface QueueMetrics { 10 | public void handleJobCompleted(Job job); 11 | public void handleJobFailed(Job job); 12 | public void handleJobStarted(Job job); 13 | public void handleJobException(Job job); 14 | public void handleJobEnqueued(Job job); 15 | public void handleWorkerAddition(EngineWorker worker); 16 | public void handleWorkerRemoval(EngineWorker worker); 17 | 18 | public DateTime getStartTime(); 19 | 20 | public long getActiveJobCount(); 21 | public long getActiveJobCount(String queueName); 22 | 23 | public long getEnqueuedJobCount(); 24 | public long getEnqueuedJobCount(String queueName); 25 | 26 | public long getCompletedJobCount(); 27 | public long getCompletedJobCount(String queueName); 28 | 29 | public long getFailedJobCount(); 30 | public long getFailedJobCount(String queueName); 31 | 32 | public long getExceptionCount(); 33 | public long getExceptionCount(String queueName); 34 | 35 | public long getRunningJobsCount(); 36 | public long getRunningJobsCount(String queueName); 37 | 38 | public long getPendingJobsCount(); 39 | public long getPendingJobsCount(String queueName); 40 | 41 | public long getHighPriorityJobsCount(String queueName); 42 | public long getMidPriorityJobsCount(String queueName); 43 | public long getLowPriorityJobsCount(String queueName); 44 | 45 | public ImmutableList getQueueNames(); 46 | 47 | public long getActiveWorkers(); 48 | public long getActiveWorkers(String queueName); 49 | 50 | void registerJobQueue(JobQueue jobQueue); 51 | } 52 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/JobQueue.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue; 2 | 3 | import com.google.common.collect.ImmutableMap; 4 | import net.johnewart.gearman.common.Job; 5 | import net.johnewart.gearman.constants.JobPriority; 6 | import net.johnewart.gearman.engine.core.QueuedJob; 7 | import net.johnewart.gearman.engine.exceptions.PersistenceException; 8 | import net.johnewart.gearman.engine.exceptions.QueueFullException; 9 | 10 | import java.util.Collection; 11 | 12 | public interface JobQueue { 13 | 14 | /** 15 | * Enqueue work 16 | * @param job 17 | */ 18 | void enqueue(Job job) throws QueueFullException, PersistenceException; 19 | 20 | long size(JobPriority priority); 21 | 22 | /** 23 | * Remove a job from the queue - simply deleting it 24 | * @param job 25 | * @return true on success, false otherwise 26 | */ 27 | boolean remove(Job job); 28 | 29 | /** 30 | * Fetch the next job waiting -- this checks high, then normal, then low 31 | * Caveat: in the normal queue, we skip over any jobs whose timestamp has not 32 | * come yet (support for epoch jobs) 33 | * 34 | * @return Next Job in the queue, null if none 35 | */ 36 | Job poll(); 37 | 38 | /** 39 | * Determine if the unique ID specified is in use. 40 | * @param uniqueID The job's unique ID 41 | * @return true or false. 42 | */ 43 | boolean uniqueIdInUse(String uniqueID); 44 | 45 | boolean isEmpty(); 46 | 47 | void setCapacity(int size); 48 | 49 | String getName(); 50 | 51 | long size(); 52 | 53 | // Data 54 | Collection getAllJobs(); 55 | 56 | Job findJobByUniqueId(String uniqueID); 57 | 58 | ImmutableMap futureCounts(); 59 | } 60 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/factories/DynamoDBPersistedJobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.factories; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 6 | import net.johnewart.gearman.engine.queue.JobQueue; 7 | import net.johnewart.gearman.engine.queue.PersistedJobQueue; 8 | import net.johnewart.gearman.engine.queue.persistence.DynamoDBPersistenceEngine; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.sql.SQLException; 13 | import java.util.Collection; 14 | 15 | public class DynamoDBPersistedJobQueueFactory implements JobQueueFactory { 16 | private static Logger LOG = LoggerFactory.getLogger(DynamoDBPersistedJobQueueFactory.class); 17 | 18 | private final DynamoDBPersistenceEngine dynamoDBPersistenceEngine; 19 | private final MetricRegistry metricRegistry; 20 | 21 | public DynamoDBPersistedJobQueueFactory(String endpoint, 22 | String user, 23 | String password, 24 | String tableName, 25 | Integer readUnits, 26 | Integer writeUnits, 27 | MetricRegistry metricRegistry) throws JobQueueFactoryException { 28 | try { 29 | this.metricRegistry = metricRegistry; 30 | this.dynamoDBPersistenceEngine = 31 | new DynamoDBPersistenceEngine(endpoint, user, password, tableName, readUnits, writeUnits, metricRegistry); 32 | } catch (SQLException e) { 33 | LOG.error("Unable to create DynamoDB persistence engine: ", e); 34 | throw new JobQueueFactoryException("Could not create the DynamoDB persistence engine!"); 35 | } 36 | } 37 | 38 | @Override 39 | public JobQueue build(String name) throws JobQueueFactoryException { 40 | return new PersistedJobQueue(name, dynamoDBPersistenceEngine, metricRegistry); 41 | } 42 | 43 | @Override 44 | public Collection loadPersistedJobs() { 45 | return this.dynamoDBPersistenceEngine.readAll(); 46 | } 47 | } 48 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/factories/JobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.factories; 2 | 3 | import net.johnewart.gearman.engine.core.QueuedJob; 4 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 5 | import net.johnewart.gearman.engine.queue.JobQueue; 6 | 7 | import java.util.Collection; 8 | 9 | public interface JobQueueFactory { 10 | JobQueue build(String name) throws JobQueueFactoryException; 11 | Collection loadPersistedJobs(); 12 | } 13 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/factories/MemoryJobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.factories; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 6 | import net.johnewart.gearman.engine.queue.JobQueue; 7 | import net.johnewart.gearman.engine.queue.PersistedJobQueue; 8 | import net.johnewart.gearman.engine.queue.persistence.MemoryPersistenceEngine; 9 | 10 | import java.util.Collection; 11 | import java.util.LinkedList; 12 | 13 | public class MemoryJobQueueFactory implements JobQueueFactory { 14 | private final MetricRegistry metricRegistry; 15 | 16 | public MemoryJobQueueFactory(MetricRegistry metricRegistry) { 17 | this.metricRegistry = metricRegistry; 18 | } 19 | 20 | public JobQueue build(String name) throws JobQueueFactoryException { 21 | return new PersistedJobQueue(name, new MemoryPersistenceEngine(), metricRegistry); 22 | } 23 | 24 | @Override 25 | public Collection loadPersistedJobs() { 26 | return new LinkedList<>(); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/factories/PostgreSQLPersistedJobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.factories; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 6 | import net.johnewart.gearman.engine.queue.JobQueue; 7 | import net.johnewart.gearman.engine.queue.PersistedJobQueue; 8 | import net.johnewart.gearman.engine.queue.persistence.PostgresPersistenceEngine; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | import java.sql.SQLException; 13 | import java.util.Collection; 14 | 15 | public class PostgreSQLPersistedJobQueueFactory implements JobQueueFactory { 16 | private static Logger LOG = LoggerFactory.getLogger(PostgreSQLPersistedJobQueueFactory.class); 17 | 18 | private final PostgresPersistenceEngine postgresQueue; 19 | private final MetricRegistry metricRegistry; 20 | 21 | public PostgreSQLPersistedJobQueueFactory(String hostname, 22 | int port, 23 | String database, 24 | String user, 25 | String password, 26 | String tableName, 27 | MetricRegistry metricRegistry) throws JobQueueFactoryException { 28 | try { 29 | this.metricRegistry = metricRegistry; 30 | this.postgresQueue = new PostgresPersistenceEngine(hostname, port, database, user, password, tableName, metricRegistry); 31 | } catch (SQLException e) { 32 | LOG.error("Unable to create PostgreSQL persistence engine: ", e); 33 | throw new JobQueueFactoryException("Could not create the PostgreSQL persistence engine!"); 34 | } 35 | } 36 | 37 | @Override 38 | public JobQueue build(String name) throws JobQueueFactoryException { 39 | return new PersistedJobQueue(name, postgresQueue, metricRegistry); 40 | } 41 | 42 | @Override 43 | public Collection loadPersistedJobs() { 44 | return this.postgresQueue.readAll(); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/factories/RedisPersistedJobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.factories; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 6 | import net.johnewart.gearman.engine.queue.JobQueue; 7 | import net.johnewart.gearman.engine.queue.PersistedJobQueue; 8 | import net.johnewart.gearman.engine.queue.persistence.RedisPersistenceEngine; 9 | 10 | import java.util.Collection; 11 | 12 | public class RedisPersistedJobQueueFactory implements JobQueueFactory { 13 | private final RedisPersistenceEngine redisQueue; 14 | private final MetricRegistry metricRegistry; 15 | 16 | public RedisPersistedJobQueueFactory(final String redisHostname, final int redisPort, MetricRegistry metricRegistry) { 17 | this.metricRegistry = metricRegistry; 18 | this.redisQueue = new RedisPersistenceEngine(redisHostname, redisPort, metricRegistry); 19 | } 20 | 21 | @Override 22 | public JobQueue build(String name) throws JobQueueFactoryException { 23 | return new PersistedJobQueue(name, redisQueue, metricRegistry); 24 | } 25 | 26 | @Override 27 | public Collection loadPersistedJobs() { 28 | return redisQueue.readAll(); 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/persistence/MemoryPersistenceEngine.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.persistence; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | 11 | public class MemoryPersistenceEngine implements PersistenceEngine { 12 | private final ConcurrentHashMap> jobHash; 13 | private final Logger LOG = LoggerFactory.getLogger(MemoryPersistenceEngine.class); 14 | private final ConcurrentHashMap jobHandleMap; 15 | 16 | public MemoryPersistenceEngine() 17 | { 18 | jobHash = new ConcurrentHashMap<>(); 19 | jobHandleMap = new ConcurrentHashMap<>(); 20 | } 21 | 22 | @Override 23 | public String getIdentifier() { 24 | return "Memory-only"; 25 | } 26 | 27 | @Override 28 | public boolean write(Job job) { 29 | getFunctionHash(job.getFunctionName()).put(job.getUniqueID(), job); 30 | jobHandleMap.put(job.getJobHandle(), job); 31 | return true; 32 | } 33 | 34 | @Override 35 | public void delete(Job job) { 36 | delete(job.getFunctionName(), job.getUniqueID()); 37 | } 38 | 39 | @Override 40 | public void delete(String functionName, String uniqueID) { 41 | Map funcHash = getFunctionHash(functionName); 42 | if(funcHash.containsKey(uniqueID)) 43 | { 44 | Job job = funcHash.get(uniqueID); 45 | 46 | if(jobHandleMap.containsKey(job.getJobHandle())) 47 | { 48 | jobHandleMap.remove(job.getJobHandle()); 49 | } 50 | 51 | funcHash.remove(uniqueID); 52 | } 53 | } 54 | 55 | @Override 56 | public void deleteAll() { 57 | jobHash.clear(); 58 | jobHandleMap.clear(); 59 | } 60 | 61 | @Override 62 | public Job findJob(String functionName, String uniqueID) { 63 | Job job = null; 64 | ConcurrentHashMap funcHash = getFunctionHash(functionName); 65 | 66 | 67 | if(funcHash != null && funcHash.containsKey(uniqueID)) 68 | { 69 | job = funcHash.get(uniqueID); 70 | } 71 | 72 | return job; 73 | } 74 | 75 | @Override 76 | public Collection readAll() { 77 | Set allJobs = new HashSet<>(); 78 | 79 | for(String functionName : jobHash.keySet()) 80 | { 81 | allJobs.addAll(getAllForFunction(functionName)); 82 | } 83 | 84 | return allJobs; 85 | } 86 | 87 | @Override 88 | public Collection getAllForFunction(String functionName) { 89 | ConcurrentHashMap funcHash = getFunctionHash(functionName); 90 | ArrayList runnableJobs = new ArrayList<>(); 91 | 92 | for( Job job : funcHash.values()) 93 | { 94 | runnableJobs.add(new QueuedJob(job)); 95 | } 96 | 97 | return runnableJobs; 98 | } 99 | 100 | private ConcurrentHashMap getFunctionHash(String functionName) 101 | { 102 | ConcurrentHashMap hash = null; 103 | if(jobHash.containsKey(functionName)) 104 | { 105 | hash = jobHash.get(functionName); 106 | } else { 107 | hash = new ConcurrentHashMap<>(); 108 | jobHash.put(functionName, hash); 109 | } 110 | 111 | return hash; 112 | } 113 | } 114 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/queue/persistence/PersistenceEngine.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.queue.persistence; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.engine.core.QueuedJob; 5 | 6 | import java.util.Collection; 7 | 8 | public interface PersistenceEngine { 9 | public String getIdentifier(); 10 | public boolean write(Job job); 11 | public void delete(Job job); 12 | public void delete(String functionName, String uniqueID); 13 | public void deleteAll(); 14 | public Job findJob(String functionName, String uniqueID); 15 | public Collection readAll(); 16 | public Collection getAllForFunction(String functionName); 17 | //public Job findJobByHandle(String jobHandle); 18 | } -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/storage/ExceptionData.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.storage; 2 | 3 | import org.joda.time.LocalDateTime; 4 | 5 | public class ExceptionData { 6 | 7 | public final String jobHandle; 8 | public final String uniqueId; 9 | public final byte[] jobData; 10 | public final byte[] exceptionData; 11 | public final LocalDateTime when; 12 | 13 | public ExceptionData(String jobHandle, String uniqueId, byte[] jobData, byte[] exceptionData, LocalDateTime when) { 14 | this.jobHandle = jobHandle; 15 | this.uniqueId = uniqueId; 16 | this.jobData = jobData; 17 | this.exceptionData = exceptionData; 18 | this.when = when; 19 | } 20 | 21 | } 22 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/storage/ExceptionStorageEngine.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.storage; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | 5 | public interface ExceptionStorageEngine { 6 | public boolean storeException(String jobHandle, String uniqueId, byte[] jobData, byte[] exceptionData); 7 | public ImmutableList getFailedJobHandles(); 8 | public ImmutableList getExceptions(int pageNum, int pageSize); 9 | public int getCount(); 10 | } 11 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/storage/MemoryExceptionStorageEngine.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.storage; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.joda.time.LocalDateTime; 5 | import org.slf4j.Logger; 6 | import org.slf4j.LoggerFactory; 7 | 8 | import java.util.*; 9 | import java.util.concurrent.ConcurrentHashMap; 10 | import java.util.concurrent.SynchronousQueue; 11 | 12 | public class MemoryExceptionStorageEngine implements ExceptionStorageEngine { 13 | 14 | private static Logger LOG = LoggerFactory.getLogger(PostgresExceptionStorageEngine.class); 15 | private final Map exceptionDataMap; 16 | private final LinkedList jobHandles; 17 | private final int maxEntries; 18 | 19 | public MemoryExceptionStorageEngine(final int maxEntries) { 20 | this.exceptionDataMap = new ConcurrentHashMap<>(); 21 | this.jobHandles = new LinkedList<>(); 22 | this.maxEntries = maxEntries; 23 | LOG.debug("Starting memory exception storage engine with " + maxEntries + " max. entries."); 24 | } 25 | 26 | @Override 27 | public boolean storeException(String jobHandle, String uniqueId, byte[] jobData, byte[] exceptionData) { 28 | 29 | synchronized (jobHandles) { 30 | if (jobHandles.size() == maxEntries) { 31 | String toRemove = jobHandles.poll(); 32 | exceptionDataMap.remove(toRemove); 33 | } 34 | } 35 | 36 | ExceptionData data = new ExceptionData(jobHandle, uniqueId, jobData, exceptionData, new LocalDateTime()); 37 | jobHandles.offer(jobHandle); 38 | exceptionDataMap.put(jobHandle, data); 39 | 40 | return true; 41 | } 42 | 43 | @Override 44 | public ImmutableList getFailedJobHandles() { 45 | return ImmutableList.copyOf(jobHandles); 46 | } 47 | 48 | @Override 49 | public ImmutableList getExceptions(int pageNum, int pageSize) { 50 | int offset = pageSize * (pageNum - 1); 51 | List exceptionDatas = new ArrayList<>(pageSize); 52 | if(offset < jobHandles.size()) { 53 | for (int i = 0; i < pageSize; i++) { 54 | int idx = offset + i; 55 | if(idx >= getCount()) break; 56 | String jobHandle = jobHandles.get(idx); 57 | exceptionDatas.add(exceptionDataMap.get(jobHandle)); 58 | } 59 | } 60 | return ImmutableList.copyOf(exceptionDatas); 61 | } 62 | 63 | @Override 64 | public int getCount() { 65 | return jobHandles.size(); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/storage/NoopExceptionStorageEngine.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.storage; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import org.slf4j.Logger; 5 | import org.slf4j.LoggerFactory; 6 | 7 | public class NoopExceptionStorageEngine implements ExceptionStorageEngine { 8 | private static Logger LOG = LoggerFactory.getLogger(NoopExceptionStorageEngine.class); 9 | 10 | public NoopExceptionStorageEngine() { 11 | LOG.info("NoOp exception storage engine initialized, exceptions will not be stored."); 12 | } 13 | 14 | @Override 15 | public boolean storeException(String jobHandle, String uniqueId, byte[] jobData, byte[] exceptionData) { 16 | return true; 17 | } 18 | 19 | @Override 20 | public ImmutableList getFailedJobHandles() { 21 | return null; 22 | } 23 | 24 | @Override 25 | public ImmutableList getExceptions(int pageNum, int pageSize) { 26 | return null; 27 | } 28 | 29 | @Override 30 | public int getCount() { 31 | return 0; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/util/LocalJobHandleFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.util; 2 | 3 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 4 | 5 | import java.util.concurrent.atomic.AtomicLong; 6 | 7 | public class LocalJobHandleFactory implements JobHandleFactory { 8 | private final AtomicLong jobHandleCounter; 9 | private final String hostName; 10 | 11 | public LocalJobHandleFactory(String hostName) { 12 | this.hostName = hostName; 13 | this.jobHandleCounter = new AtomicLong(0L); 14 | } 15 | /** 16 | * Returns the next available job handle 17 | * @return 18 | * the next available job handle 19 | */ 20 | public byte[] getNextJobHandle() { 21 | String handle = "H:".concat(hostName).concat(":").concat(String.valueOf(jobHandleCounter.incrementAndGet())); 22 | return handle.getBytes(); 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /gearman-engine/src/main/java/net/johnewart/gearman/engine/util/LocalUniqueIdFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.util; 2 | 3 | import java.util.concurrent.atomic.AtomicLong; 4 | 5 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 6 | 7 | public class LocalUniqueIdFactory implements UniqueIdFactory { 8 | private final AtomicLong uniqueIdCounter; 9 | 10 | public LocalUniqueIdFactory() { 11 | this.uniqueIdCounter = new AtomicLong(0L); 12 | } 13 | 14 | @Override 15 | public String generateUniqueId() { 16 | long uniqueId = uniqueIdCounter.incrementAndGet(); 17 | return String.valueOf(uniqueId); 18 | } 19 | } 20 | 21 | -------------------------------------------------------------------------------- /gearman-engine/src/test/java/net/johnewart/gearman/engine/JobHandleFactoryTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine; 2 | 3 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 4 | import net.johnewart.gearman.engine.util.LocalJobHandleFactory; 5 | import org.hamcrest.core.Is; 6 | import org.hamcrest.core.IsNot; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | public class JobHandleFactoryTest { 11 | private final JobHandleFactory jobHandleFactory; 12 | private final String hostname = "foobar.quiddle.com"; 13 | 14 | public JobHandleFactoryTest() { 15 | jobHandleFactory = new LocalJobHandleFactory(hostname); 16 | } 17 | 18 | @Test 19 | public void testHandleGenerationWorks() 20 | { 21 | String jobHandle = new String(jobHandleFactory.getNextJobHandle()); 22 | String[] parts = jobHandle.split(":"); 23 | 24 | Assert.assertThat("There are three parts to the handle", 25 | parts.length, 26 | Is.is(3)); 27 | 28 | Assert.assertThat("The first part is 'H'", 29 | parts[0], 30 | Is.is("H")); 31 | 32 | Assert.assertThat("The middle is the hostname", 33 | parts[1], 34 | Is.is("foobar.quiddle.com")); 35 | 36 | Assert.assertThat("The last part is non-zero", 37 | Long.parseLong(parts[2]), 38 | IsNot.not(0L)); 39 | } 40 | 41 | 42 | 43 | } 44 | -------------------------------------------------------------------------------- /gearman-engine/src/test/java/net/johnewart/gearman/engine/QueuedJobTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine; 2 | 3 | 4 | import net.johnewart.gearman.constants.JobPriority; 5 | import net.johnewart.gearman.engine.core.QueuedJob; 6 | import org.hamcrest.core.Is; 7 | import org.junit.Assert; 8 | import org.junit.Test; 9 | 10 | public class QueuedJobTest { 11 | @Test 12 | public void testHashCode() throws Exception 13 | { 14 | QueuedJob jobA = new QueuedJob("frobozz", -1, JobPriority.HIGH, "function"); 15 | QueuedJob jobB = new QueuedJob("frobozz", 1024, JobPriority.HIGH, "function"); 16 | 17 | Assert.assertThat("Hash codes represent a unique set of data points", 18 | jobA.hashCode() == jobB.hashCode(), 19 | Is.is(false)); 20 | } 21 | 22 | @Test 23 | public void testEquality() throws Exception 24 | { 25 | QueuedJob jobA = new QueuedJob("frobozz", -1, JobPriority.HIGH, "function"); 26 | QueuedJob jobB = new QueuedJob("frobozz", -1, JobPriority.HIGH, "function"); 27 | 28 | Assert.assertThat("Queued Jobs are equal if their data points are the same", 29 | jobA.equals(jobB), 30 | Is.is(true)); 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /gearman-engine/src/test/java/net/johnewart/gearman/engine/factories/JobFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.factories; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 5 | import net.johnewart.gearman.constants.JobPriority; 6 | import org.joda.time.DateTime; 7 | import org.joda.time.Seconds; 8 | 9 | import java.util.UUID; 10 | 11 | public class JobFactory { 12 | static JobHandleFactory jobHandleFactory = new TestJobHandleFactory(); 13 | 14 | public static Job generateForegroundJob(String functionName) 15 | { 16 | String uuid = UUID.randomUUID().toString(); 17 | byte[] data = {'f','o','o'}; 18 | JobPriority priority = JobPriority.NORMAL; 19 | boolean isBackground = false; 20 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 21 | } 22 | 23 | public static Job generateBackgroundJob(String functionName) 24 | { 25 | String uuid = UUID.randomUUID().toString(); 26 | byte[] data = {'b','a','r'}; 27 | JobPriority priority = JobPriority.NORMAL; 28 | boolean isBackground = true; 29 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 30 | } 31 | 32 | public static Job generateFutureJob(String functionName, Seconds seconds) { 33 | String uuid = UUID.randomUUID().toString(); 34 | byte[] data = {'f','l','u','x',' ','c','a','p'}; 35 | JobPriority priority = JobPriority.NORMAL; 36 | boolean isBackground = true; 37 | long whenToRun = new DateTime().plus(seconds).toDate().getTime() / 1000; 38 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, whenToRun); 39 | } 40 | 41 | public static Job generateHighPriorityBackgroundJob(String functionName) 42 | { 43 | String uuid = UUID.randomUUID().toString(); 44 | byte[] data = {'s','u','p','e','r'}; 45 | JobPriority priority = JobPriority.HIGH; 46 | boolean isBackground = true; 47 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); } 48 | 49 | public static Job generateLowPriorityBackgroundJob(String functionName) 50 | { 51 | String uuid = UUID.randomUUID().toString(); 52 | byte[] data = {'s','u','p','e','r'}; 53 | JobPriority priority = JobPriority.LOW; 54 | boolean isBackground = true; 55 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 56 | } 57 | } 58 | 59 | -------------------------------------------------------------------------------- /gearman-engine/src/test/java/net/johnewart/gearman/engine/factories/TestJobHandleFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.factories; 2 | 3 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 4 | import net.johnewart.gearman.engine.util.LocalJobHandleFactory; 5 | 6 | public class TestJobHandleFactory implements JobHandleFactory { 7 | private JobHandleFactory jobHandleFactory; 8 | 9 | public TestJobHandleFactory() { 10 | this.jobHandleFactory = new LocalJobHandleFactory("localhost"); 11 | } 12 | 13 | @Override 14 | public byte[] getNextJobHandle() { 15 | return jobHandleFactory.getNextJobHandle(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gearman-engine/src/test/java/net/johnewart/gearman/engine/factories/TestUniqueIdFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.engine.factories; 2 | 3 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 4 | import net.johnewart.gearman.engine.util.LocalUniqueIdFactory; 5 | 6 | public class TestUniqueIdFactory implements UniqueIdFactory { 7 | private UniqueIdFactory uniqueIdFactory; 8 | 9 | public TestUniqueIdFactory() { 10 | this.uniqueIdFactory = new LocalUniqueIdFactory(); 11 | } 12 | 13 | @Override 14 | public String generateUniqueId() { 15 | return uniqueIdFactory.generateUniqueId(); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /gearman-example/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | gearman-java 7 | net.johnewart.gearman 8 | 0.8.11-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | gearman-example 13 | 14 | 15 | 16 | org.apache.commons 17 | commons-lang3 18 | 3.1 19 | 20 | 21 | net.johnewart.gearman 22 | gearman-client 23 | ${project.version} 24 | 25 | 26 | net.johnewart.gearman 27 | gearman-embedded-server 28 | ${project.version} 29 | 30 | 31 | -------------------------------------------------------------------------------- /gearman-example/src/main/java/net/johnewart/gearman/example/ClientDemo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.example; 2 | 3 | import net.johnewart.gearman.client.NetworkGearmanClient; 4 | import net.johnewart.gearman.common.JobStatus; 5 | import net.johnewart.gearman.common.events.GearmanClientEventListener; 6 | import net.johnewart.gearman.constants.JobPriority; 7 | import net.johnewart.gearman.exceptions.NoServersAvailableException; 8 | import net.johnewart.gearman.exceptions.WorkException; 9 | import net.johnewart.gearman.exceptions.WorkExceptionException; 10 | import net.johnewart.gearman.exceptions.WorkFailException; 11 | 12 | import java.io.IOException; 13 | 14 | public class ClientDemo { 15 | private ClientDemo() { } 16 | 17 | public static void main(String... args) 18 | { 19 | GearmanClientEventListener eventListener = new GearmanClientEventListener() { 20 | @Override 21 | public void handleWorkData(String jobHandle, byte[] data) { 22 | System.err.println("Received data update for job " + jobHandle); 23 | } 24 | 25 | @Override 26 | public void handleWorkWarning(String jobHandle, byte[] warning) { 27 | System.err.println("Received warning for job " + jobHandle); 28 | } 29 | 30 | @Override 31 | public void handleWorkStatus(String jobHandle, JobStatus jobStatus) { 32 | System.err.println("Received status update for job " + jobHandle); 33 | System.err.println("Status: " + jobStatus.getNumerator() + " / " + jobStatus.getDenominator()); 34 | } 35 | }; 36 | 37 | try { 38 | byte data[] = "This is a test".getBytes(); 39 | NetworkGearmanClient client = new NetworkGearmanClient("localhost", 4730); 40 | client.addHostToList("localhost", 4731); 41 | client.registerEventListener(eventListener); 42 | 43 | while(true) 44 | { 45 | try { 46 | byte[] result = client.submitJob("reverse", data, JobPriority.NORMAL); 47 | System.err.println("Result: " + new String(result)); 48 | } catch (WorkException e) { 49 | if(e instanceof WorkFailException) 50 | System.err.println("Job " + e.getJobHandle() + " failed."); 51 | else 52 | System.err.println("Job " + e.getJobHandle() + " exception: " + ((WorkExceptionException) e).getMessage()); 53 | 54 | e.printStackTrace(); 55 | } 56 | 57 | try { 58 | Thread.sleep(2000); 59 | } catch (InterruptedException e) { 60 | e.printStackTrace(); 61 | } 62 | } 63 | } catch (IOException ioe) { 64 | System.err.println("Couldn't connect: " + ioe); 65 | } catch (NoServersAvailableException nsae) { 66 | System.err.println("Can't connect to any servers."); 67 | } 68 | } 69 | } 70 | -------------------------------------------------------------------------------- /gearman-example/src/main/java/net/johnewart/gearman/example/EmbeddedServerDemo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.example; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.events.WorkEvent; 5 | import net.johnewart.gearman.common.interfaces.GearmanClient; 6 | import net.johnewart.gearman.common.interfaces.GearmanFunction; 7 | import net.johnewart.gearman.embedded.EmbeddedGearmanClient; 8 | import net.johnewart.gearman.embedded.EmbeddedGearmanServer; 9 | import net.johnewart.gearman.embedded.EmbeddedGearmanWorker; 10 | import net.johnewart.gearman.exceptions.JobSubmissionException; 11 | import net.johnewart.gearman.exceptions.WorkException; 12 | 13 | import java.util.Arrays; 14 | import java.util.Calendar; 15 | import java.util.Date; 16 | 17 | public class EmbeddedServerDemo { 18 | EmbeddedGearmanServer server = new EmbeddedGearmanServer(); 19 | 20 | public EmbeddedServerDemo() { 21 | GearmanClient client = new EmbeddedGearmanClient(server); 22 | EmbeddedGearmanWorker worker = new EmbeddedGearmanWorker(server); 23 | 24 | TestFunction testFunction = new TestFunction(); 25 | worker.registerCallback("test", testFunction); 26 | 27 | Thread workerThread = new Thread(worker); 28 | workerThread.start(); 29 | 30 | byte[] data = {'4','2','1','9','3','5','8','7'}; 31 | byte[] data2 = {'4','9','1','9','3','5','8','6'}; 32 | 33 | try { 34 | byte[] result = client.submitJob("test", data); 35 | System.err.println("Data: " + new String(data)); 36 | System.err.println("Result: " + new String(result)); 37 | 38 | Thread.sleep(500); 39 | 40 | byte[] result2 = client.submitJob("test", data2); 41 | System.err.println("Data: " + new String(data2)); 42 | System.err.println("Result: " + new String(result2)); 43 | 44 | Calendar c = Calendar.getInstance(); 45 | c.add(Calendar.SECOND, 10); 46 | Date whenToRun = c.getTime(); 47 | String jobHandle = client.submitFutureJob("test", data2, whenToRun); 48 | System.err.println("Job handle for future job: " + jobHandle); 49 | Thread.sleep(45000); 50 | System.err.println("Job should be complete..."); 51 | 52 | worker.stopWork(); 53 | workerThread.join(); 54 | } catch (JobSubmissionException e) { 55 | e.printStackTrace(); 56 | } catch (WorkException e) { 57 | e.printStackTrace(); 58 | } catch (InterruptedException e) { 59 | e.printStackTrace(); 60 | } 61 | } 62 | 63 | class TestFunction implements GearmanFunction { 64 | @Override 65 | public byte[] process(WorkEvent workEvent) { 66 | Job job = workEvent.job; 67 | byte[] datacopy = Arrays.copyOf(job.getData(), job.getData().length); 68 | Arrays.sort(datacopy); 69 | return datacopy; 70 | } 71 | } 72 | 73 | public static void main(String ... args) { 74 | new EmbeddedServerDemo(); 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /gearman-example/src/main/java/net/johnewart/gearman/example/WorkerDemo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.example; 2 | 3 | import net.johnewart.gearman.client.NetworkGearmanWorker; 4 | import net.johnewart.gearman.common.events.WorkEvent; 5 | import org.apache.commons.lang3.ArrayUtils; 6 | import net.johnewart.gearman.common.interfaces.GearmanFunction; 7 | import net.johnewart.gearman.common.Job; 8 | import net.johnewart.gearman.net.Connection; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class WorkerDemo { 13 | private static Logger LOG = LoggerFactory.getLogger(WorkerDemo.class); 14 | 15 | static class ReverseFunction implements GearmanFunction 16 | { 17 | @Override 18 | public byte[] process(WorkEvent workEvent) { 19 | Job job = workEvent.job; 20 | byte[] data = job.getData(); 21 | String function = job.getFunctionName(); 22 | LOG.debug("Got data for function " + function); 23 | ArrayUtils.reverse(data); 24 | return data; 25 | } 26 | } 27 | 28 | public static void main(String... args) 29 | { 30 | try { 31 | byte data[] = "This is a test".getBytes(); 32 | NetworkGearmanWorker worker = new NetworkGearmanWorker.Builder() 33 | .withConnection(new Connection("localhost", 4730)) 34 | .build(); 35 | 36 | worker.registerCallback("reverse", new ReverseFunction()); 37 | 38 | worker.doWork(); 39 | } catch (Exception e) { 40 | LOG.error("oops!"); 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /gearman-example/src/main/java/net/johnewart/gearman/example/WorkerPoolDemo.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.example; 2 | 3 | import net.johnewart.gearman.client.NetworkGearmanWorkerPool; 4 | import net.johnewart.gearman.common.events.WorkEvent; 5 | import net.johnewart.gearman.common.interfaces.GearmanFunction; 6 | import net.johnewart.gearman.net.Connection; 7 | import org.apache.commons.lang3.ArrayUtils; 8 | import net.johnewart.gearman.common.Job; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | public class WorkerPoolDemo { 13 | private static Logger LOG = LoggerFactory.getLogger(WorkerPoolDemo.class); 14 | 15 | static class ReverseFunction implements GearmanFunction 16 | { 17 | @Override 18 | public byte[] process(WorkEvent workEvent) { 19 | Job job = workEvent.job; 20 | byte[] data = job.getData(); 21 | String function = job.getFunctionName(); 22 | LOG.debug("Got data for function " + function); 23 | ArrayUtils.reverse(data); 24 | return data; 25 | } 26 | } 27 | 28 | public static void main(String... args) 29 | { 30 | try { 31 | byte data[] = "This is a test".getBytes(); 32 | NetworkGearmanWorkerPool workerPool = new NetworkGearmanWorkerPool.Builder() 33 | .threads(2) 34 | .withConnection(new Connection("localhost", 4730)) 35 | .build(); 36 | 37 | workerPool.registerCallback("reverse", new ReverseFunction()); 38 | 39 | workerPool.doWork(); 40 | } catch (Exception e) { 41 | LOG.error("Error: ", e); 42 | } 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gearman-integration/README.md: -------------------------------------------------------------------------------- 1 | # Integration test suites 2 | 3 | This package contains integration tests that perform actions such as: 4 | 5 | * Spin up a server, client and workers and interact with each other over 6 | the wire 7 | * Construct a cluster of servers and push work through them 8 | * Talk to other implementations of the server to test the client / 9 | worker code 10 | 11 | 12 | -------------------------------------------------------------------------------- /gearman-integration/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 5 | 6 | gearman-java 7 | net.johnewart.gearman 8 | 0.8.11-SNAPSHOT 9 | 10 | 4.0.0 11 | 12 | gearman-integration 13 | 14 | 15 | 16 | net.johnewart.gearman 17 | gearman-server 18 | ${project.version} 19 | 20 | 21 | net.johnewart.gearman 22 | gearman-common 23 | ${project.version} 24 | 25 | 26 | net.johnewart.gearman 27 | gearman-client 28 | ${project.version} 29 | 30 | 31 | org.apache.commons 32 | commons-lang3 33 | 3.1 34 | 35 | 36 | 37 | 38 | -------------------------------------------------------------------------------- /gearman-integration/src/main/java/net/johnewart/gearman/integ/ReverseFunc.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.integ; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.events.WorkEvent; 5 | import net.johnewart.gearman.common.interfaces.GearmanFunction; 6 | import net.johnewart.gearman.common.interfaces.GearmanWorker; 7 | import org.apache.commons.lang3.ArrayUtils; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.io.IOException; 12 | 13 | public class ReverseFunc implements GearmanFunction { 14 | private final Logger LOG = LoggerFactory.getLogger(ReverseFunc.class); 15 | 16 | @Override 17 | public byte[] process(WorkEvent workEvent) { 18 | final Job job = workEvent.job; 19 | final GearmanWorker worker = workEvent.worker; 20 | 21 | LOG.debug(String.format("Processing job '%s' with data '%s'", job.getFunctionName(), new String(job.getData()))); 22 | byte[] data = job.getData().clone(); 23 | ArrayUtils.reverse(data); 24 | for(int i = 0; i < 10; i++) { 25 | try { 26 | worker.sendStatus(job, i, 10); 27 | } catch (IOException e) { 28 | LOG.error("Unable to send status: ", e); 29 | } 30 | } 31 | return data; 32 | } 33 | } -------------------------------------------------------------------------------- /gearman-integration/src/main/java/net/johnewart/gearman/integ/WorkerRunner.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.integ; 2 | 3 | import net.johnewart.gearman.client.NetworkGearmanWorker; 4 | import net.johnewart.gearman.common.interfaces.GearmanFunction; 5 | import net.johnewart.gearman.common.interfaces.GearmanWorker; 6 | import net.johnewart.gearman.net.Connection; 7 | 8 | import java.util.Map; 9 | import java.util.Set; 10 | 11 | 12 | public class WorkerRunner implements Runnable { 13 | private GearmanWorker worker; 14 | private Map functions; 15 | private Set connections; 16 | 17 | public WorkerRunner(Set connections, Map functions) { 18 | this.functions = functions; 19 | this.connections = connections; 20 | } 21 | 22 | @Override 23 | public void run() { 24 | NetworkGearmanWorker.Builder builder = new NetworkGearmanWorker.Builder(); 25 | 26 | for(Connection c : connections) { 27 | builder.withConnection(c); 28 | } 29 | 30 | worker = builder.build(); 31 | 32 | for(String function : functions.keySet()) { 33 | worker.registerCallback(function, functions.get(function)); 34 | } 35 | 36 | worker.doWork(); 37 | } 38 | 39 | public void stop() { 40 | worker.stopWork(); 41 | } 42 | } 43 | -------------------------------------------------------------------------------- /gearman-server/config-1.yml: -------------------------------------------------------------------------------- 1 | port: 4740 2 | httpPort: 9005 3 | enableSSL: false 4 | debugging: true 5 | hostName: node1 6 | cluster: 7 | hazelcast: 8 | port: 5701 9 | hosts: 10 | - 127.0.0.1:5702 11 | 12 | -------------------------------------------------------------------------------- /gearman-server/config-2.yml: -------------------------------------------------------------------------------- 1 | port: 4741 2 | httpPort: 9006 3 | enableSSL: false 4 | debugging: true 5 | hostName: node2 6 | cluster: 7 | hazelcast: 8 | port: 5702 9 | hosts: 10 | - 127.0.0.1:5701 11 | 12 | -------------------------------------------------------------------------------- /gearman-server/config-dynamodb-local.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: dynamodb 8 | dynamoDB: 9 | endpoint: http://localhost:8000 10 | accessKey: your_access_key 11 | secretKey: your_secret_key 12 | table: gearman 13 | -------------------------------------------------------------------------------- /gearman-server/config-dynamodb.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: dynamodb 8 | dynamoDB: 9 | region: "us-east-1" 10 | accessKey: your_access_key 11 | secretKey: your_secret_key 12 | table: gearman 13 | -------------------------------------------------------------------------------- /gearman-server/config-nodebug.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: memory -------------------------------------------------------------------------------- /gearman-server/config-postgres.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: postgres 8 | postgreSQL: 9 | host: localhost 10 | port: 5432 11 | dbName: gearman 12 | user: gearman 13 | password: gearman 14 | table: gearman_00 15 | exceptionStore: 16 | engine: postgres 17 | postgreSQL: 18 | host: localhost 19 | port: 5432 20 | dbName: gearman 21 | user: gearman 22 | password: gearman 23 | table: gearman_exceptions 24 | 25 | -------------------------------------------------------------------------------- /gearman-server/config-redis.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: redis 8 | redis: 9 | host: localhost 10 | port: 8005 11 | -------------------------------------------------------------------------------- /gearman-server/config.yml: -------------------------------------------------------------------------------- 1 | port: 4730 2 | httpPort: 8080 3 | enableSSL: false 4 | debugging: true 5 | hostName: localhost 6 | persistenceEngine: 7 | engine: memory 8 | exceptionStore: 9 | engine: memory -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/GearmanDaemon.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server; 2 | 3 | import net.johnewart.gearman.server.config.DefaultServerConfiguration; 4 | import net.johnewart.gearman.server.config.GearmanServerConfiguration; 5 | import net.johnewart.gearman.server.net.ServerListener; 6 | import net.johnewart.gearman.server.web.WebListener; 7 | import org.slf4j.LoggerFactory; 8 | import org.yaml.snakeyaml.Yaml; 9 | 10 | import java.io.InputStream; 11 | import java.nio.file.Files; 12 | import java.nio.file.Paths; 13 | 14 | public class GearmanDaemon { 15 | private static final org.slf4j.Logger LOG = LoggerFactory.getLogger(GearmanDaemon.class); 16 | 17 | public static void main(String... args) 18 | { 19 | final String configFile; 20 | 21 | if (args.length != 1) { 22 | configFile = "config.yml"; 23 | } else { 24 | configFile = args[0]; 25 | } 26 | 27 | 28 | final GearmanServerConfiguration serverConfiguration = loadFromConfigOrGenerateDefaultConfig(configFile); 29 | final ServerListener serverListener = new ServerListener(serverConfiguration); 30 | final WebListener webListener = new WebListener(serverConfiguration); 31 | 32 | try { 33 | webListener.start(); 34 | serverListener.start(); 35 | } catch (Exception e) { 36 | e.printStackTrace(); 37 | } 38 | } 39 | 40 | private static GearmanServerConfiguration loadFromConfigOrGenerateDefaultConfig(final String configFile) { 41 | GearmanServerConfiguration serverConfiguration = null; 42 | try (InputStream in = Files.newInputStream(Paths.get(configFile))) { 43 | Yaml yaml = new Yaml(); 44 | 45 | serverConfiguration 46 | = yaml.loadAs(in, GearmanServerConfiguration.class); 47 | 48 | System.out.println(serverConfiguration.toString()); 49 | 50 | LOG.info("Starting Gearman Server with settings from " + configFile + "..."); 51 | 52 | } catch (Exception e) { 53 | LOG.error("Can't load " + configFile + ": ", e); 54 | } 55 | 56 | if (serverConfiguration == null) { 57 | LOG.info("Starting Gearman Server with default settings ..."); 58 | serverConfiguration = new DefaultServerConfiguration(); 59 | } 60 | 61 | return serverConfiguration; 62 | } 63 | 64 | 65 | } 66 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/config/ClusterConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.config; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import net.johnewart.gearman.server.cluster.core.ClusterJobManager; 5 | import net.johnewart.gearman.server.cluster.queue.factories.HazelcastJobQueueFactory; 6 | import net.johnewart.gearman.server.cluster.util.HazelcastJobHandleFactory; 7 | import net.johnewart.gearman.server.cluster.util.HazelcastUniqueIdFactory; 8 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 9 | import net.johnewart.gearman.engine.core.JobManager; 10 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 11 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 12 | import net.johnewart.gearman.server.config.ServerConfiguration; 13 | import net.johnewart.gearman.server.util.JobQueueMonitor; 14 | 15 | public class ClusterConfiguration { 16 | 17 | private HazelcastConfiguration hazelcastConfiguration; 18 | 19 | public ClusterConfiguration() { 20 | } 21 | 22 | public ClusterConfiguration(HazelcastConfiguration config) { 23 | this.hazelcastConfiguration = config; 24 | } 25 | 26 | public void setHazelcast(HazelcastConfiguration hazelcastConfiguration) { 27 | this.hazelcastConfiguration = hazelcastConfiguration; 28 | } 29 | 30 | public HazelcastConfiguration getHazelcast() { 31 | return hazelcastConfiguration; 32 | } 33 | 34 | public HazelcastInstance getHazelcastInstance() { 35 | return getHazelcast().getHazelcastInstance(); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/config/HazelcastConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.config; 2 | 3 | import com.hazelcast.config.*; 4 | import com.hazelcast.core.Hazelcast; 5 | import com.hazelcast.core.HazelcastInstance; 6 | 7 | import java.util.LinkedList; 8 | import java.util.List; 9 | 10 | public class HazelcastConfiguration { 11 | private List hosts = new LinkedList<>(); 12 | private HazelcastInstance hazelcast; 13 | private int port; 14 | 15 | public int getPort() { 16 | return port; 17 | } 18 | 19 | public void setPort(int port) { 20 | this.port = port; 21 | } 22 | 23 | public List getHosts() { 24 | return hosts; 25 | } 26 | 27 | public void setHosts(final List hosts) { 28 | this.hosts = hosts; 29 | } 30 | 31 | public HazelcastInstance getHazelcastInstance() { 32 | 33 | if (hazelcast == null) { 34 | Config cfg = new Config(); 35 | NetworkConfig network = new NetworkConfig(); 36 | network.setPort(getPort()); 37 | network.setPortAutoIncrement(true); 38 | cfg.setNetworkConfig(network); 39 | 40 | JoinConfig join = network.getJoin(); 41 | 42 | if(getHosts() != null && getHosts().size() > 0) { 43 | System.err.println("Using unicast config!"); 44 | 45 | join.getMulticastConfig().setEnabled(false); 46 | 47 | for(String host : getHosts()) { 48 | join.getTcpIpConfig().addMember(host); 49 | } 50 | 51 | join.getTcpIpConfig().setEnabled(true); 52 | } else { 53 | System.err.println("Using multicast config!"); 54 | join.getTcpIpConfig().setEnabled(false); 55 | join.getMulticastConfig().setEnabled(true); 56 | join.getMulticastConfig().setMulticastTimeoutSeconds(15); 57 | join.getMulticastConfig().setMulticastGroup("224.2.2.3"); 58 | join.getMulticastConfig().setMulticastPort(54327); 59 | //cfg.setProperty("hazelcast.initial.min.cluster.size","2"); 60 | //join.getMulticastConfig().setMulticastGroup(MULTICAST_ADDRESS); 61 | //join.getMulticastConfig().setMulticastPort(PORT_NUMBER); 62 | 63 | } 64 | 65 | 66 | //network.getInterfaces().setEnabled(true).addInterface("10.45.67.*"); 67 | 68 | /* 69 | MapConfig mapCfg = new MapConfig(); 70 | mapCfg.setName("testMap"); 71 | mapCfg.setBackupCount(2); 72 | mapCfg.getMaxSizeConfig().setSize(10000); 73 | mapCfg.setTimeToLiveSeconds(300); 74 | 75 | MapStoreConfig mapStoreCfg = new MapStoreConfig(); 76 | mapStoreCfg.setClassName("com.hazelcast.examples.DummyStore").setEnabled(true); 77 | mapCfg.setMapStoreConfig(mapStoreCfg); 78 | 79 | NearCacheConfig nearCacheConfig = new NearCacheConfig(); 80 | nearCacheConfig.setMaxSize(1000).setMaxIdleSeconds(120).setTimeToLiveSeconds(300); 81 | mapCfg.setNearCacheConfig(nearCacheConfig); 82 | 83 | cfg.addMapConfig(mapCfg);*/ 84 | 85 | hazelcast = Hazelcast.newHazelcastInstance(cfg); 86 | } 87 | 88 | return hazelcast; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/core/HazelcastJob.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.core; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.hazelcast.nio.ObjectDataInput; 5 | import com.hazelcast.nio.ObjectDataOutput; 6 | import com.hazelcast.nio.serialization.DataSerializable; 7 | import net.johnewart.gearman.common.Job; 8 | 9 | import java.io.IOException; 10 | 11 | public class HazelcastJob extends Job implements DataSerializable { 12 | 13 | public HazelcastJob() { 14 | } 15 | 16 | public HazelcastJob(Job job) { 17 | cloneOtherJob(job); 18 | } 19 | 20 | public Job toJob() { 21 | return new Job(this); 22 | } 23 | 24 | // TODO: Optimize. 25 | @Override 26 | public void writeData(ObjectDataOutput output) throws IOException { 27 | ObjectMapper mapper = new ObjectMapper(); 28 | output.writeUTF(mapper.writeValueAsString(this)); 29 | } 30 | 31 | @Override 32 | public void readData(ObjectDataInput input) throws IOException { 33 | ObjectMapper mapper = new ObjectMapper(); 34 | Job job = mapper.readValue(input.readUTF(), this.getClass()); 35 | this.cloneOtherJob(job); 36 | } 37 | } 38 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/core/WorkMessage.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.core; 2 | 3 | import com.fasterxml.jackson.databind.ObjectMapper; 4 | import com.hazelcast.nio.ObjectDataInput; 5 | import com.hazelcast.nio.ObjectDataOutput; 6 | import com.hazelcast.nio.serialization.DataSerializable; 7 | import net.johnewart.gearman.constants.PacketType; 8 | 9 | import java.io.IOException; 10 | 11 | public class WorkMessage implements DataSerializable { 12 | public String uniqueId, functionName; 13 | public PacketType type; 14 | public byte[] data; 15 | 16 | public WorkMessage() { } 17 | 18 | public WorkMessage(String uniqueId, String functionName, PacketType type, byte[] data) { 19 | this.uniqueId = uniqueId; 20 | this.functionName = functionName; 21 | this.type = type; 22 | if (data != null) { 23 | this.data = data.clone(); 24 | } else { 25 | this.data = new byte[0]; 26 | } 27 | } 28 | 29 | // TODO: Optimize. 30 | @Override 31 | public void writeData(ObjectDataOutput output) throws IOException { 32 | ObjectMapper mapper = new ObjectMapper(); 33 | output.writeUTF(mapper.writeValueAsString(this)); 34 | } 35 | 36 | @Override 37 | public void readData(ObjectDataInput input) throws IOException { 38 | ObjectMapper mapper = new ObjectMapper(); 39 | WorkMessage message = mapper.readValue(input.readUTF(), this.getClass()); 40 | this.uniqueId = message.uniqueId; 41 | this.functionName = message.functionName; 42 | this.type = message.type; 43 | this.data = message.data.clone(); 44 | } 45 | } 46 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/queue/factories/HazelcastJobQueueFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.queue.factories; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import net.johnewart.gearman.server.cluster.queue.HazelcastJobQueue; 5 | import net.johnewart.gearman.engine.core.QueuedJob; 6 | import net.johnewart.gearman.engine.exceptions.JobQueueFactoryException; 7 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import java.util.Collection; 12 | import java.util.HashSet; 13 | 14 | import static java.lang.String.format; 15 | 16 | public class HazelcastJobQueueFactory implements JobQueueFactory { 17 | private final Logger LOG = LoggerFactory.getLogger(HazelcastJobQueueFactory.class); 18 | 19 | private final HazelcastInstance hazelcast; 20 | 21 | public HazelcastJobQueueFactory(HazelcastInstance hazelcast) { 22 | LOG.debug("Starting HazelcastJobQueueFactory"); 23 | this.hazelcast = hazelcast; 24 | } 25 | 26 | public HazelcastJobQueue build(String name) throws JobQueueFactoryException { 27 | return new HazelcastJobQueue(name, hazelcast); 28 | } 29 | 30 | @Override 31 | public Collection loadPersistedJobs() { 32 | return new HashSet<>(); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/util/HazelcastJobHandleFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.util; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import com.hazelcast.core.IAtomicLong; 5 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 6 | 7 | public class HazelcastJobHandleFactory implements JobHandleFactory { 8 | 9 | private final HazelcastInstance hazelcast; 10 | private final String clusterHostname; 11 | final IAtomicLong jobHandleCounter; 12 | 13 | public HazelcastJobHandleFactory(HazelcastInstance hazelcast, String clusterHostname) { 14 | this.hazelcast = hazelcast; 15 | this.clusterHostname = clusterHostname; 16 | jobHandleCounter = hazelcast.getAtomicLong("jobhandlecounter"); 17 | } 18 | 19 | public final byte[] getNextJobHandle() { 20 | String handle = "H:".concat(clusterHostname).concat(":").concat(String.valueOf(jobHandleCounter.incrementAndGet())); 21 | return handle.getBytes(); 22 | } 23 | 24 | } 25 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/util/HazelcastUniqueIdFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.util; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import com.hazelcast.core.IdGenerator; 5 | 6 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 7 | 8 | public class HazelcastUniqueIdFactory implements UniqueIdFactory { 9 | private final IdGenerator idGenerator; 10 | 11 | public HazelcastUniqueIdFactory(HazelcastInstance hazelcast) { 12 | idGenerator = hazelcast.getIdGenerator("job-ids"); 13 | } 14 | 15 | @Override 16 | public String generateUniqueId() { 17 | return String.valueOf(idGenerator.newId()); 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/cluster/web/ClusterWebListener.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.web; 2 | 3 | import net.johnewart.gearman.server.web.WebListener; 4 | 5 | /** 6 | * Created with IntelliJ IDEA. 7 | * User: jewart 8 | * Date: 6/24/14 9 | * Time: 3:59 PM 10 | * To change this template use File | Settings | File Templates. 11 | */ 12 | public class ClusterWebListener { 13 | /* private final ClusterConfiguration serverConfiguration; 14 | 15 | public ClusterWebListener(ClusterConfiguration serverConfiguration) { 16 | super(serverConfiguration); 17 | this.serverConfiguration = serverConfiguration; 18 | } 19 | 20 | @Override 21 | public Map getServletMappings() { 22 | final ClusterServlet clusterServlet = 23 | new ClusterServlet(); 24 | 25 | Map map = super.getServletMappings(); 26 | map.put("/cluster/*", clusterServlet); 27 | 28 | return map; 29 | } */ 30 | } 31 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/DefaultServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 5 | import net.johnewart.gearman.engine.core.JobManager; 6 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 7 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 8 | import net.johnewart.gearman.engine.queue.factories.MemoryJobQueueFactory; 9 | import net.johnewart.gearman.engine.storage.NoopExceptionStorageEngine; 10 | import net.johnewart.gearman.engine.util.LocalJobHandleFactory; 11 | import net.johnewart.gearman.engine.util.LocalUniqueIdFactory; 12 | import net.johnewart.gearman.server.util.JobQueueMonitor; 13 | import net.johnewart.gearman.server.util.SnapshottingJobQueueMonitor; 14 | 15 | import java.net.InetAddress; 16 | import java.net.UnknownHostException; 17 | 18 | // Sane defaults. 19 | public class DefaultServerConfiguration extends GearmanServerConfiguration { 20 | 21 | private final JobManager jobManager; 22 | private final JobQueueFactory jobQueueFactory; 23 | private final JobQueueMonitor jobQueueMonitor; 24 | private final JobHandleFactory jobHandleFactory; 25 | private final UniqueIdFactory uniqueIdFactory; 26 | private final MetricRegistry registry; 27 | 28 | public DefaultServerConfiguration() { 29 | this.registry = new MetricRegistry(); 30 | this.jobHandleFactory = new LocalJobHandleFactory(getHostName()); 31 | this.jobQueueFactory = new MemoryJobQueueFactory(registry); 32 | this.uniqueIdFactory = new LocalUniqueIdFactory(); 33 | this.jobManager = new JobManager(jobQueueFactory, jobHandleFactory, uniqueIdFactory, new NoopExceptionStorageEngine(), getQueueMetrics()); 34 | this.jobQueueMonitor = new SnapshottingJobQueueMonitor(getQueueMetrics()); 35 | } 36 | 37 | @Override 38 | public int getPort() { 39 | return 4730; 40 | } 41 | 42 | @Override 43 | public int getHttpPort() { 44 | return 8080; 45 | } 46 | 47 | @Override 48 | public boolean isSSLEnabled() { 49 | return false; 50 | } 51 | 52 | @Override 53 | public boolean isDebugging() { 54 | return false; 55 | } 56 | 57 | @Override 58 | public String getHostName() { 59 | try { 60 | return InetAddress.getLocalHost().getHostName(); 61 | } catch (UnknownHostException e) { 62 | return "localhost"; 63 | } 64 | } 65 | 66 | @Override 67 | public JobQueueFactory getJobQueueFactory() { 68 | return jobQueueFactory; 69 | } 70 | 71 | @Override 72 | public JobManager getJobManager() { 73 | return jobManager; 74 | } 75 | 76 | @Override 77 | public JobQueueMonitor getJobQueueMonitor() { 78 | return jobQueueMonitor; 79 | } 80 | 81 | @Override 82 | public JobHandleFactory getJobHandleFactory() { 83 | return jobHandleFactory; 84 | } 85 | 86 | @Override 87 | public UniqueIdFactory getUniqueIdFactory() { 88 | return uniqueIdFactory; 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/ExceptionStoreConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config; 2 | 3 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 4 | import net.johnewart.gearman.engine.queue.factories.MemoryJobQueueFactory; 5 | import net.johnewart.gearman.engine.queue.factories.PostgreSQLPersistedJobQueueFactory; 6 | import net.johnewart.gearman.engine.queue.factories.RedisPersistedJobQueueFactory; 7 | import net.johnewart.gearman.engine.storage.ExceptionStorageEngine; 8 | import net.johnewart.gearman.engine.storage.MemoryExceptionStorageEngine; 9 | import net.johnewart.gearman.engine.storage.NoopExceptionStorageEngine; 10 | import net.johnewart.gearman.engine.storage.PostgresExceptionStorageEngine; 11 | import net.johnewart.gearman.server.config.persistence.PostgreSQLConfiguration; 12 | import net.johnewart.gearman.server.config.persistence.RedisConfiguration; 13 | 14 | import java.sql.SQLException; 15 | 16 | public class ExceptionStoreConfiguration { 17 | 18 | private static final String ENGINE_MEMORY = "memory"; 19 | private static final String ENGINE_POSTGRES = "postgres"; 20 | private static final int MAX_MEMORY_ENTRIES = 5000; 21 | 22 | private RedisConfiguration redis; 23 | private PostgreSQLConfiguration postgreSQL; 24 | private String engine; 25 | private ExceptionStorageEngine exceptionStorageEngine; 26 | 27 | public String getEngine() { 28 | return engine; 29 | } 30 | 31 | public void setEngine(String engine) { 32 | this.engine = engine; 33 | } 34 | 35 | public PostgreSQLConfiguration getPostgreSQL() { 36 | return postgreSQL; 37 | } 38 | 39 | public void setPostgreSQL(PostgreSQLConfiguration postgreSQL) { 40 | this.postgreSQL = postgreSQL; 41 | } 42 | 43 | public ExceptionStorageEngine getExceptionStorageEngine() { 44 | if(exceptionStorageEngine == null) { 45 | switch (getEngine()) { 46 | case ENGINE_MEMORY: 47 | exceptionStorageEngine = new MemoryExceptionStorageEngine(MAX_MEMORY_ENTRIES); 48 | break; 49 | case ENGINE_POSTGRES: 50 | try { 51 | exceptionStorageEngine = new PostgresExceptionStorageEngine( 52 | postgreSQL.getHost(), 53 | postgreSQL.getPort(), 54 | postgreSQL.getDbName(), 55 | postgreSQL.getUser(), 56 | postgreSQL.getPassword(), 57 | postgreSQL.getTable() 58 | ); 59 | } catch (SQLException e) { 60 | e.printStackTrace(); 61 | exceptionStorageEngine = new NoopExceptionStorageEngine(); 62 | } 63 | break; 64 | default: 65 | exceptionStorageEngine = new NoopExceptionStorageEngine(); 66 | } 67 | } 68 | 69 | return exceptionStorageEngine; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/ServerConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config; 2 | 3 | import com.codahale.metrics.MetricRegistry; 4 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 5 | import net.johnewart.gearman.engine.core.JobManager; 6 | import net.johnewart.gearman.engine.core.UniqueIdFactory; 7 | import net.johnewart.gearman.engine.queue.factories.JobQueueFactory; 8 | import net.johnewart.gearman.server.util.JobQueueMonitor; 9 | 10 | public interface ServerConfiguration { 11 | int getPort(); 12 | 13 | int getHttpPort(); 14 | 15 | boolean isSSLEnabled(); 16 | 17 | boolean isDebugging(); 18 | 19 | String getHostName(); 20 | 21 | JobQueueFactory getJobQueueFactory(); 22 | 23 | JobManager getJobManager(); 24 | 25 | JobQueueMonitor getJobQueueMonitor(); 26 | 27 | JobHandleFactory getJobHandleFactory(); 28 | 29 | UniqueIdFactory getUniqueIdFactory(); 30 | 31 | MetricRegistry getMetricRegistry(); 32 | 33 | } 34 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/persistence/DynamoDBConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config.persistence; 2 | 3 | import com.amazonaws.regions.Region; 4 | import com.amazonaws.regions.Regions; 5 | import com.amazonaws.regions.ServiceAbbreviations; 6 | 7 | public class DynamoDBConfiguration { 8 | private String endpoint; 9 | private String secretKey; 10 | private String accessKey; 11 | private String region; 12 | 13 | // Some sane defaults 14 | private String table = "GearmanJobs"; 15 | private Integer writeUnits = 10; 16 | private Integer readUnits = 10; 17 | 18 | public String getTable() { 19 | return table; 20 | } 21 | 22 | public void setTable(String table) { 23 | this.table = table; 24 | } 25 | 26 | public String getSecretKey() { 27 | return secretKey; 28 | } 29 | 30 | public void setSecretKey(String secretKey) { 31 | this.secretKey = secretKey; 32 | } 33 | 34 | public String getAccessKey() { 35 | return accessKey; 36 | } 37 | 38 | public void setAccessKey(String accessKey) { 39 | this.accessKey = accessKey; 40 | } 41 | 42 | public Integer getWriteUnits() { 43 | return writeUnits; 44 | } 45 | 46 | public void setWriteUnits(Integer writeUnits) { 47 | this.writeUnits = writeUnits; 48 | } 49 | 50 | public Integer getReadUnits() { 51 | return readUnits; 52 | } 53 | 54 | public void setReadUnits(Integer readUnits) { 55 | this.readUnits = readUnits; 56 | } 57 | 58 | public String getEndpoint() { 59 | // If no endpoint manually specified, then try to discover 60 | // based on region (if specified) 61 | if (this.endpoint == null && region != null) { 62 | this.endpoint = 63 | Region.getRegion(Regions.fromName(region)) 64 | .getServiceEndpoint(ServiceAbbreviations.Dynamodb); 65 | } 66 | 67 | return endpoint; 68 | 69 | } 70 | 71 | public void setEndpoint(String endpoint) { 72 | this.endpoint = endpoint; 73 | } 74 | 75 | public String getRegion() { return region; } 76 | 77 | public void setRegion(String region) { 78 | this.region = region; 79 | } 80 | } 81 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/persistence/PostgreSQLConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config.persistence; 2 | 3 | public class PostgreSQLConfiguration { 4 | public String host; 5 | public int port; 6 | private String dbName; 7 | private String password; 8 | private String user; 9 | private String table = "jobs"; 10 | 11 | public String getTable() { 12 | return table; 13 | } 14 | 15 | public void setTable(String table) { 16 | this.table = table; 17 | } 18 | 19 | public String getDbName() { 20 | return dbName; 21 | } 22 | 23 | public void setDbName(String dbname) { 24 | this.dbName = dbname; 25 | } 26 | 27 | public String getPassword() { 28 | return password; 29 | } 30 | 31 | public void setPassword(String password) { 32 | this.password = password; 33 | } 34 | 35 | public String getUser() { 36 | return user; 37 | } 38 | 39 | public void setUser(String user) { 40 | this.user = user; 41 | } 42 | 43 | public String getHost() { 44 | return host; 45 | } 46 | 47 | public void setHost(String host) { 48 | this.host = host; 49 | } 50 | 51 | public int getPort() { 52 | return port; 53 | } 54 | 55 | public void setPort(int port) { 56 | this.port = port; 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/config/persistence/RedisConfiguration.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.config.persistence; 2 | 3 | public class RedisConfiguration { 4 | public String host; 5 | public int port; 6 | 7 | public String getHost() { 8 | return host; 9 | } 10 | 11 | public void setHost(String host) { 12 | this.host = host; 13 | } 14 | 15 | public int getPort() { 16 | return port; 17 | } 18 | 19 | public void setPort(int port) { 20 | this.port = port; 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/core/JobTracker.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.core; 2 | 3 | 4 | import net.johnewart.gearman.common.Job; 5 | 6 | /** 7 | * Active job tracker 8 | */ 9 | 10 | public interface JobTracker { 11 | Job findByUniqueId(String uniqueId); 12 | Job findByJobHandle(String jobHandle); 13 | 14 | } 15 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/Decoder.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import com.google.common.primitives.Ints; 4 | import io.netty.buffer.ByteBuf; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.ReplayingDecoder; 7 | import net.johnewart.gearman.common.packets.Packet; 8 | import net.johnewart.gearman.common.packets.PacketFactory; 9 | import net.johnewart.gearman.util.ByteArray; 10 | import org.slf4j.Logger; 11 | import org.slf4j.LoggerFactory; 12 | 13 | import java.util.Arrays; 14 | import java.util.List; 15 | 16 | public class Decoder extends ReplayingDecoder { 17 | 18 | private final Logger LOG = LoggerFactory.getLogger(Decoder.class); 19 | private Packet packet; 20 | private byte[] packetData; 21 | private int messageLength; 22 | private ByteArray textCommand; 23 | 24 | public Decoder() { 25 | this.reset(); 26 | } 27 | 28 | @Override 29 | protected void decode(ChannelHandlerContext ctx, ByteBuf buffer, List decoded) 30 | throws Exception { 31 | 32 | 33 | switch (state()) { 34 | case HEADER: 35 | byte[] header = new byte[12]; 36 | byte firstByte = buffer.readByte(); 37 | textCommand = null; 38 | 39 | // Binary packets are prefixed with 0 40 | if(firstByte == 0) 41 | { 42 | header[0] = 0; 43 | buffer.readBytes(header, 1, 11); 44 | messageLength = Ints.fromByteArray(Arrays.copyOfRange(header, 8, 12)); 45 | packetData = Arrays.copyOf(header, messageLength + 12); 46 | } else { 47 | textCommand = new ByteArray(1024); 48 | textCommand.push(firstByte); 49 | } 50 | 51 | checkpoint(DecodingState.PAYLOAD); 52 | 53 | case PAYLOAD: 54 | if(textCommand == null) 55 | { 56 | 57 | buffer.readBytes(packetData, 12, messageLength); 58 | try { 59 | packet = PacketFactory.packetFromBytes(packetData); 60 | LOG.debug("---> " + packet.getType()); 61 | decoded.add(packet); 62 | } finally { 63 | this.reset(); 64 | } 65 | } else { 66 | int textOffset = 1; 67 | byte b; 68 | do { 69 | b = buffer.readByte(); 70 | textCommand.push(b); 71 | } while (b != 10); 72 | 73 | try { 74 | String result = textCommand.toString().trim(); 75 | LOG.debug("Text command: " + result); 76 | decoded.add(result); 77 | } finally { 78 | this.reset(); 79 | } 80 | } 81 | break; 82 | 83 | default: 84 | throw new Exception("Unknown decoding state: " + state()); 85 | } 86 | } 87 | 88 | private void reset() { 89 | checkpoint(DecodingState.HEADER); 90 | this.packet = null; 91 | this.packetData = null; 92 | this.messageLength = -1; 93 | } 94 | 95 | public enum DecodingState { 96 | HEADER, 97 | PAYLOAD, 98 | TEXT // Text command 99 | } 100 | } -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/Encoder.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import io.netty.buffer.ByteBuf; 4 | import io.netty.channel.ChannelHandler; 5 | import io.netty.channel.ChannelHandlerContext; 6 | import io.netty.handler.codec.MessageToByteEncoder; 7 | import net.johnewart.gearman.common.packets.Packet; 8 | import net.johnewart.gearman.constants.GearmanConstants; 9 | import org.slf4j.Logger; 10 | import org.slf4j.LoggerFactory; 11 | 12 | @ChannelHandler.Sharable 13 | public class Encoder extends MessageToByteEncoder { 14 | 15 | private static Logger LOG = LoggerFactory.getLogger(Encoder.class); 16 | 17 | public static Encoder getInstance() { 18 | return InstanceHolder.INSTANCE; 19 | } 20 | 21 | public static byte[] encodePacket(Packet packet) 22 | throws IllegalArgumentException { 23 | 24 | LOG.debug("<--- " + packet.getType()); 25 | return packet.toByteArray(); 26 | } 27 | 28 | public static byte[] encodeString(String message) 29 | throws IllegalArgumentException { 30 | LOG.debug("<--- " + message); 31 | return message.getBytes(GearmanConstants.CHARSET); 32 | } 33 | 34 | @Override 35 | protected void encode(ChannelHandlerContext ctx, Object msg, ByteBuf out) { 36 | if (msg instanceof Packet) { 37 | out.writeBytes(encodePacket((Packet) msg)); 38 | } else if (msg instanceof String) { 39 | out.writeBytes(encodeString((String) msg)); 40 | } else { 41 | LOG.error("Unable to encode this thing: " + msg); 42 | } 43 | } 44 | 45 | private static final class InstanceHolder { 46 | private static final Encoder INSTANCE = new Encoder(); 47 | } 48 | 49 | } 50 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/GearmanServerInitializer.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import io.netty.channel.ChannelInitializer; 4 | import io.netty.channel.ChannelPipeline; 5 | import io.netty.channel.socket.SocketChannel; 6 | import io.netty.handler.ssl.SslHandler; 7 | import net.johnewart.gearman.server.net.ssl.GearmanSslContextFactory; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import javax.net.ssl.SSLEngine; 12 | 13 | public class GearmanServerInitializer extends ChannelInitializer { 14 | private final NetworkManager networkManager; 15 | private final boolean enableSSL; 16 | private final Logger LOG = LoggerFactory.getLogger(GearmanServerInitializer.class); 17 | 18 | 19 | public GearmanServerInitializer(NetworkManager networkManager, 20 | boolean enableSSL) 21 | { 22 | this.networkManager = networkManager; 23 | this.enableSSL = enableSSL; 24 | } 25 | 26 | @Override 27 | public void initChannel(SocketChannel ch) throws Exception { 28 | ChannelPipeline pipeline = ch.pipeline(); 29 | 30 | if(enableSSL) 31 | { 32 | LOG.info("Enabling SSL"); 33 | SSLEngine engine = 34 | GearmanSslContextFactory.getServerContext().createSSLEngine(); 35 | engine.setUseClientMode(false); 36 | pipeline.addLast("ssl", new SslHandler(engine)); 37 | } 38 | 39 | pipeline.addLast("decoder", new Decoder()); 40 | pipeline.addLast("encoder", new Encoder()); 41 | 42 | pipeline.addLast("handler", new PacketHandler(networkManager)); 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/NetworkEngineClient.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import io.netty.channel.Channel; 4 | import net.johnewart.gearman.common.JobStatus; 5 | import net.johnewart.gearman.common.interfaces.EngineClient; 6 | import net.johnewart.gearman.common.packets.Packet; 7 | import net.johnewart.gearman.common.packets.response.WorkCompleteResponse; 8 | import net.johnewart.gearman.common.packets.response.WorkDataResponse; 9 | import net.johnewart.gearman.common.packets.response.WorkExceptionResponse; 10 | import net.johnewart.gearman.common.packets.response.WorkFailResponse; 11 | import net.johnewart.gearman.common.packets.response.WorkStatus; 12 | import net.johnewart.gearman.common.packets.response.WorkWarningResponse; 13 | import net.johnewart.gearman.common.Job; 14 | 15 | public class NetworkEngineClient implements EngineClient { 16 | private final Channel channel; 17 | private Job currentJob; 18 | 19 | public NetworkEngineClient(Channel channel) 20 | { 21 | this.channel = channel; 22 | } 23 | 24 | @Override 25 | public Job getCurrentJob() { 26 | return currentJob; 27 | } 28 | 29 | @Override 30 | public void setCurrentJob(Job job) { 31 | this.currentJob = job; 32 | } 33 | 34 | @Override 35 | public void sendWorkResults(String jobHandle, byte[] data) 36 | { 37 | send(new WorkCompleteResponse(jobHandle, data)); 38 | } 39 | 40 | @Override 41 | public void sendWorkData(String jobHandle, byte[] data) { 42 | send(new WorkDataResponse(jobHandle, data)); 43 | } 44 | 45 | @Override 46 | public void sendWorkException(String jobHandle, byte[] exception) { 47 | send(new WorkExceptionResponse(jobHandle, exception)); 48 | } 49 | 50 | @Override 51 | public void sendWorkFail(String jobHandle) { 52 | send(new WorkFailResponse(jobHandle)); 53 | } 54 | 55 | @Override 56 | public void sendWorkWarning(String jobHandle, byte[] warning) { 57 | send(new WorkWarningResponse(jobHandle, warning)); 58 | } 59 | 60 | @Override 61 | public void sendWorkStatus(JobStatus jobStatus) { 62 | send(new WorkStatus(jobStatus)); 63 | } 64 | 65 | @Override 66 | public void send(Packet packet) 67 | { 68 | channel.writeAndFlush(packet); 69 | } 70 | 71 | } 72 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/NetworkEngineWorker.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import io.netty.channel.Channel; 4 | import net.johnewart.gearman.common.interfaces.EngineWorker; 5 | import net.johnewart.gearman.common.packets.Packet; 6 | import net.johnewart.gearman.common.packets.response.NoOp; 7 | 8 | import java.util.HashSet; 9 | import java.util.Set; 10 | import java.util.concurrent.atomic.AtomicBoolean; 11 | 12 | public class NetworkEngineWorker implements EngineWorker { 13 | private final Channel channel; 14 | private final Set abilities; 15 | private Boolean awake; 16 | 17 | public NetworkEngineWorker(Channel channel) 18 | { 19 | this.channel = channel; 20 | this.abilities = new HashSet<>(); 21 | this.awake = new Boolean(true); 22 | } 23 | 24 | public void send(Packet packet) 25 | { 26 | channel.writeAndFlush(packet); 27 | } 28 | 29 | public void addAbility(String ability) 30 | { 31 | this.abilities.add(ability); 32 | } 33 | 34 | @Override 35 | public Set getAbilities() { 36 | return abilities; 37 | } 38 | 39 | 40 | @Override 41 | public void wakeUp() 42 | { 43 | synchronized (awake) { 44 | if(!awake) { 45 | send(new NoOp()); 46 | awake = true; 47 | } 48 | } 49 | } 50 | 51 | @Override 52 | public void markAsleep() { 53 | synchronized (awake) { 54 | awake = false; 55 | } 56 | } 57 | 58 | public void removeAbility(String functionName) { 59 | this.abilities.remove(functionName); 60 | } 61 | } 62 | 63 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/ssl/GearmanSslContextFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net.ssl; 2 | 3 | import javax.net.ssl.KeyManagerFactory; 4 | import javax.net.ssl.SSLContext; 5 | import java.security.KeyStore; 6 | import java.security.Security; 7 | 8 | public class GearmanSslContextFactory { 9 | 10 | private static final String PROTOCOL = "TLS"; 11 | private static final SSLContext SERVER_CONTEXT; 12 | private static final SSLContext CLIENT_CONTEXT; 13 | 14 | static { 15 | String algorithm = Security.getProperty("ssl.KeyManagerFactory.algorithm"); 16 | if (algorithm == null) { 17 | algorithm = "SunX509"; 18 | } 19 | 20 | SSLContext serverContext = null; 21 | SSLContext clientContext = null; 22 | try { 23 | KeyStore ks = KeyStore.getInstance("JKS"); 24 | ks.load(GearmanKeyStore.asInputStream(), 25 | GearmanKeyStore.getKeyStorePassword()); 26 | 27 | // Set up key manager factory to use our key store 28 | KeyManagerFactory kmf = KeyManagerFactory.getInstance(algorithm); 29 | kmf.init(ks, GearmanKeyStore.getCertificatePassword()); 30 | 31 | // Initialize the SSLContext to work with our key managers. 32 | serverContext = SSLContext.getInstance(PROTOCOL); 33 | serverContext.init(kmf.getKeyManagers(), null, null); 34 | } catch (Exception e) { 35 | throw new Error( 36 | "Failed to initialize the server-side SSLContext", e); 37 | } 38 | 39 | try { 40 | clientContext = SSLContext.getInstance(PROTOCOL); 41 | clientContext.init(null, GearmanTrustManagerFactory.getTrustManagers(), null); 42 | } catch (Exception e) { 43 | throw new Error( 44 | "Failed to initialize the client-side SSLContext", e); 45 | } 46 | 47 | SERVER_CONTEXT = serverContext; 48 | CLIENT_CONTEXT = clientContext; 49 | } 50 | 51 | public static SSLContext getServerContext() { 52 | return SERVER_CONTEXT; 53 | } 54 | 55 | public static SSLContext getClientContext() { 56 | return CLIENT_CONTEXT; 57 | } 58 | } -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/net/ssl/GearmanTrustManagerFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net.ssl; 2 | 3 | import org.slf4j.Logger; 4 | import org.slf4j.LoggerFactory; 5 | 6 | import javax.net.ssl.ManagerFactoryParameters; 7 | import javax.net.ssl.TrustManager; 8 | import javax.net.ssl.TrustManagerFactorySpi; 9 | import javax.net.ssl.X509TrustManager; 10 | import java.security.InvalidAlgorithmParameterException; 11 | import java.security.KeyStore; 12 | import java.security.KeyStoreException; 13 | import java.security.cert.CertificateException; 14 | import java.security.cert.X509Certificate; 15 | 16 | public class GearmanTrustManagerFactory extends TrustManagerFactorySpi { 17 | 18 | private static final TrustManager DUMMY_TRUST_MANAGER = new X509TrustManager() { 19 | private final Logger LOG = LoggerFactory.getLogger(GearmanTrustManagerFactory.class); 20 | 21 | public X509Certificate[] getAcceptedIssuers() { 22 | return new X509Certificate[0]; 23 | } 24 | 25 | public void checkClientTrusted( 26 | X509Certificate[] chain, String authType) throws CertificateException { 27 | // Always trust - it is an example. 28 | // You should do something in the real world. 29 | // You will reach here only if you enabled client certificate auth, 30 | // as described in SecureChatSslContextFactory. 31 | LOG.warn( 32 | "UNKNOWN CLIENT CERTIFICATE: " + chain[0].getSubjectDN()); 33 | } 34 | 35 | public void checkServerTrusted( 36 | X509Certificate[] chain, String authType) throws CertificateException { 37 | // Always trust - it is an example. 38 | // You should do something in the real world. 39 | LOG.warn( 40 | "UNKNOWN SERVER CERTIFICATE: " + chain[0].getSubjectDN()); 41 | } 42 | }; 43 | 44 | public static TrustManager[] getTrustManagers() { 45 | return new TrustManager[] { DUMMY_TRUST_MANAGER }; 46 | } 47 | 48 | @Override 49 | protected TrustManager[] engineGetTrustManagers() { 50 | return getTrustManagers(); 51 | } 52 | 53 | @Override 54 | protected void engineInit(KeyStore keystore) throws KeyStoreException { 55 | // Unused 56 | } 57 | 58 | @Override 59 | protected void engineInit(ManagerFactoryParameters managerFactoryParameters) 60 | throws InvalidAlgorithmParameterException { 61 | // Unused 62 | } 63 | } -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/util/JobQueueMetrics.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.util; 2 | 3 | import net.johnewart.gearman.engine.queue.JobQueue; 4 | import net.johnewart.shuzai.DifferentialTimeSeries; 5 | import net.johnewart.shuzai.Frequency; 6 | import net.johnewart.shuzai.SampleMethod; 7 | import net.johnewart.shuzai.TimeSeries; 8 | import org.joda.time.DateTime; 9 | 10 | import java.math.BigDecimal; 11 | import java.util.Map; 12 | import java.util.concurrent.TimeUnit; 13 | 14 | public class JobQueueMetrics { 15 | public final TimeSeries queued, failed, completed, exceptions, 16 | highJobs, midJobs, lowJobs, futureJobs; 17 | 18 | public JobQueueMetrics() { 19 | this.highJobs = new TimeSeries(); 20 | this.midJobs = new TimeSeries(); 21 | this.lowJobs = new TimeSeries(); 22 | this.futureJobs = new TimeSeries(); 23 | this.queued = new DifferentialTimeSeries(); 24 | this.failed = new DifferentialTimeSeries(); 25 | this.completed = new DifferentialTimeSeries(); 26 | this.exceptions = new DifferentialTimeSeries(); 27 | } 28 | 29 | public JobQueueMetrics(TimeSeries queued, TimeSeries failed, 30 | TimeSeries completed, TimeSeries exceptions, 31 | TimeSeries highJobs, TimeSeries midJobs, 32 | TimeSeries lowJobs, TimeSeries futureJobs) { 33 | this.queued = queued; 34 | this.failed = failed; 35 | this.completed = completed; 36 | this.exceptions = exceptions; 37 | this.highJobs = highJobs; 38 | this.midJobs = midJobs; 39 | this.lowJobs = lowJobs; 40 | this.futureJobs = futureJobs; 41 | } 42 | 43 | public JobQueueMetrics compact() { 44 | return new JobQueueMetrics( 45 | compactTimeSeries(queued, SampleMethod.MEAN), 46 | compactTimeSeries(failed, SampleMethod.SUM), 47 | compactTimeSeries(completed, SampleMethod.SUM), 48 | compactTimeSeries(exceptions, SampleMethod.SUM), 49 | compactTimeSeries(highJobs, SampleMethod.MEAN), 50 | compactTimeSeries(midJobs, SampleMethod.MEAN), 51 | compactTimeSeries(lowJobs, SampleMethod.MEAN), 52 | compactTimeSeries(futureJobs, SampleMethod.MEAN) 53 | ); 54 | } 55 | 56 | 57 | private TimeSeries compactTimeSeries(TimeSeries original, SampleMethod method) { 58 | TimeSeries ts = original.downSample(Frequency.of(5, TimeUnit.MINUTES), 59 | method); 60 | DateTime start = ts.index().last(); 61 | DateTime end = original.index().last(); 62 | 63 | if (start != null && end != null) { 64 | for (Map.Entry entry : ts.dataWindow(start, end).entrySet()) { 65 | ts.add(entry.getKey(), entry.getValue()); 66 | } 67 | } 68 | 69 | return ts; 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/util/JobQueueMonitor.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.util; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.collect.ImmutableMap; 5 | 6 | import java.util.List; 7 | 8 | /** 9 | * Created with IntelliJ IDEA. 10 | * User: jewart 11 | * Date: 9/25/13 12 | * Time: 10:14 AM 13 | * To change this template use File | Settings | File Templates. 14 | */ 15 | public interface JobQueueMonitor { 16 | ImmutableMap getSnapshots(); 17 | ImmutableList getSystemSnapshots(); 18 | } 19 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/util/JobQueueSnapshot.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.util; 2 | 3 | import java.util.Date; 4 | 5 | import com.google.common.collect.ImmutableMap; 6 | 7 | import net.johnewart.gearman.constants.JobPriority; 8 | 9 | public class JobQueueSnapshot { 10 | private Date timestamp; 11 | private long immediate; 12 | private long future; 13 | private ImmutableMap futureJobCounts; 14 | private ImmutableMap priorityCounts; 15 | 16 | public JobQueueSnapshot() { 17 | this.timestamp = new Date(); 18 | this.immediate = 0; 19 | this.future = 0; 20 | this.futureJobCounts = ImmutableMap.of(); 21 | this.priorityCounts = ImmutableMap.of(); 22 | } 23 | 24 | public JobQueueSnapshot(Date timestamp, 25 | long immediate, 26 | long future, 27 | ImmutableMap futureJobCounts, 28 | ImmutableMap priorityCounts) 29 | { 30 | this.timestamp = timestamp; 31 | this.immediate = immediate; 32 | this.future = future; 33 | this.futureJobCounts = futureJobCounts; 34 | this.priorityCounts = priorityCounts; 35 | } 36 | 37 | public Date getTimestamp() { 38 | return timestamp; 39 | } 40 | 41 | public long getImmediate() { 42 | return immediate; 43 | } 44 | 45 | public long getFuture() { 46 | return future; 47 | } 48 | 49 | public ImmutableMap getFutureJobCounts() { 50 | return futureJobCounts; 51 | } 52 | 53 | public ImmutableMap getPriorityCounts() { 54 | return priorityCounts; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/util/NoopJobQueueMonitor.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.util; 2 | 3 | import com.google.common.collect.ImmutableList; 4 | import com.google.common.collect.ImmutableMap; 5 | 6 | 7 | public class NoopJobQueueMonitor implements JobQueueMonitor { 8 | 9 | @Override 10 | public ImmutableMap getSnapshots() { 11 | return ImmutableMap.of(); 12 | } 13 | 14 | @Override 15 | public ImmutableList getSystemSnapshots() { 16 | return ImmutableList.of(); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/util/SystemSnapshot.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.util; 2 | 3 | import java.util.Date; 4 | 5 | public class SystemSnapshot { 6 | private final Date timestamp; 7 | private final Long totalJobsQueued; 8 | private final Long totalJobsProcessed; 9 | private final Long jobsQueuedSinceLastSnapshot; 10 | private final Long jobsProcessedSinceLastSnapshot; 11 | private final Long totalJobsPending; 12 | private final Long heapUsed; 13 | private final Long heapSize; 14 | 15 | public SystemSnapshot(Long totalJobsQueued, 16 | Long totalJobsProcessed, 17 | Long jobsQueuedSinceLastSnapshot, 18 | Long jobsProcessedSinceLastSnapshot, 19 | Long totalJobsPending, 20 | Long heapSize, 21 | Long heapUsed) 22 | { 23 | this.timestamp = new Date(); 24 | this.totalJobsProcessed = totalJobsProcessed; 25 | this.totalJobsQueued = totalJobsQueued; 26 | this.jobsProcessedSinceLastSnapshot = jobsProcessedSinceLastSnapshot; 27 | this.jobsQueuedSinceLastSnapshot = jobsQueuedSinceLastSnapshot; 28 | this.totalJobsPending = totalJobsPending; 29 | this.heapUsed = heapUsed; 30 | this.heapSize = heapSize; 31 | } 32 | 33 | public Date getTimestamp() { 34 | return timestamp; 35 | } 36 | 37 | public Long getTotalJobsQueued() { 38 | return totalJobsQueued; 39 | } 40 | 41 | public Long getTotalJobsProcessed() { 42 | return totalJobsProcessed; 43 | } 44 | 45 | public Long getJobsQueuedSinceLastSnapshot() { 46 | return jobsQueuedSinceLastSnapshot; 47 | } 48 | 49 | public Long getJobsProcessedSinceLastSnapshot() { 50 | return jobsProcessedSinceLastSnapshot; 51 | } 52 | 53 | public Long getTotalJobsPending() { 54 | return totalJobsPending; 55 | } 56 | 57 | public Long getHeapUsed() { 58 | return heapUsed; 59 | } 60 | 61 | public Long getHeapSize() { 62 | return heapSize; 63 | } 64 | } 65 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/ClusterServlet.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.TemplateException; 5 | import net.johnewart.gearman.server.config.GearmanServerConfiguration; 6 | import org.slf4j.Logger; 7 | import org.slf4j.LoggerFactory; 8 | 9 | import javax.servlet.ServletException; 10 | import javax.servlet.http.HttpServlet; 11 | import javax.servlet.http.HttpServletRequest; 12 | import javax.servlet.http.HttpServletResponse; 13 | import java.io.IOException; 14 | import java.io.OutputStream; 15 | import java.io.OutputStreamWriter; 16 | 17 | public class ClusterServlet extends HttpServlet { 18 | private final Logger LOG = LoggerFactory.getLogger(ClusterServlet.class); 19 | private static Configuration cfg = new Configuration(); 20 | private final GearmanServerConfiguration serverConfiguration; 21 | 22 | public ClusterServlet(GearmanServerConfiguration serverConfiguration) { 23 | this.serverConfiguration = serverConfiguration; 24 | } 25 | 26 | @Override 27 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 28 | { 29 | cfg.setClassForTemplateLoading(ClusterServlet.class, "templates"); 30 | cfg.setTemplateUpdateDelay(0); 31 | 32 | try { 33 | final OutputStream output = resp.getOutputStream(); 34 | OutputStreamWriter wr = new OutputStreamWriter(output); 35 | 36 | if(serverConfiguration.getCluster() != null) { 37 | cfg.getTemplate("cluster.ftl").process(new ClusterView(serverConfiguration.getCluster().getHazelcastInstance()), wr); 38 | } else { 39 | cfg.getTemplate("nocluster.ftl").process(null, wr); 40 | } 41 | 42 | } catch (IOException ioe) { 43 | ioe.printStackTrace(); 44 | } catch (TemplateException e) { 45 | e.printStackTrace(); 46 | } 47 | 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/ClusterView.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import com.hazelcast.core.Member; 5 | import com.hazelcast.core.Partition; 6 | 7 | import java.util.Set; 8 | 9 | public class ClusterView { 10 | 11 | private final HazelcastInstance hazelcast; 12 | 13 | public ClusterView(HazelcastInstance hazelcast) { 14 | this.hazelcast = hazelcast; 15 | } 16 | 17 | public Set getClusterMembers() { 18 | return hazelcast.getCluster().getMembers(); 19 | } 20 | 21 | public Set getPartitions() { 22 | return hazelcast.getPartitionService().getPartitions(); 23 | } 24 | 25 | 26 | } 27 | 28 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/DashboardServlet.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import com.fasterxml.jackson.core.JsonFactory; 4 | import freemarker.template.Configuration; 5 | import freemarker.template.TemplateException; 6 | import net.johnewart.gearman.engine.metrics.QueueMetrics; 7 | import net.johnewart.gearman.server.util.JobQueueMonitor; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | import java.io.OutputStream; 17 | import java.io.OutputStreamWriter; 18 | 19 | public class DashboardServlet extends HttpServlet { 20 | private static final String CONTENT_TYPE = "text/html"; 21 | private JobQueueMonitor jobQueueMonitor; 22 | private QueueMetrics queueMetrics; 23 | private static final JsonFactory jsonFactory = new JsonFactory(); 24 | private final Logger LOG = LoggerFactory.getLogger(DashboardServlet.class); 25 | private static Configuration cfg = new Configuration(); 26 | 27 | public DashboardServlet(JobQueueMonitor jobQueueMonitor, QueueMetrics queueMetrics) 28 | { 29 | this.jobQueueMonitor = jobQueueMonitor; 30 | this.queueMetrics = queueMetrics; 31 | } 32 | 33 | @Override 34 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 35 | { 36 | cfg.setClassForTemplateLoading(DashboardServlet.class, "templates"); 37 | cfg.setTemplateUpdateDelay(0); 38 | 39 | final boolean queues = Boolean.parseBoolean(req.getParameter("queues")); 40 | final String jobQueueName = req.getParameter("jobQueue"); 41 | 42 | String templateName; 43 | try { 44 | final OutputStream output = resp.getOutputStream(); 45 | OutputStreamWriter wr = new OutputStreamWriter(output); 46 | 47 | if(queues) 48 | { 49 | cfg.getTemplate("queues.ftl").process(new StatusView(jobQueueMonitor, queueMetrics), wr); 50 | } else { 51 | if(jobQueueName != null) 52 | { 53 | cfg.getTemplate("queue.ftl").process(new JobQueueStatusView(jobQueueMonitor, queueMetrics, jobQueueName), wr); 54 | } else { 55 | cfg.getTemplate("index.ftl").process(new StatusView(jobQueueMonitor, queueMetrics), wr); 56 | } 57 | } 58 | 59 | } catch (IOException ioe) { 60 | ioe.printStackTrace(); 61 | } catch (TemplateException e) { 62 | e.printStackTrace(); 63 | } 64 | 65 | } 66 | 67 | 68 | } 69 | 70 | 71 | 72 | 73 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/DateFormatter.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | public class DateFormatter { 4 | public final static long ONE_MILLISECOND = 1; 5 | public final static long MILLISECONDS_IN_A_SECOND = 1000; 6 | 7 | public final static long ONE_SECOND = 1000; 8 | public final static long SECONDS_IN_A_MINUTE = 60; 9 | 10 | public final static long ONE_MINUTE = ONE_SECOND * 60; 11 | public final static long MINUTES_IN_AN_HOUR = 60; 12 | 13 | public final static long ONE_HOUR = ONE_MINUTE * 60; 14 | public final static long HOURS_IN_A_DAY = 24; 15 | public final static long ONE_DAY = ONE_HOUR * 24; 16 | public final static long DAYS_IN_A_YEAR = 365; 17 | 18 | private DateFormatter() { } 19 | 20 | public static TimeMap buildTimeMap(Number n) { 21 | TimeMap res = null; 22 | 23 | if (n != null) { 24 | long duration = n.longValue(); 25 | 26 | duration /= ONE_MILLISECOND; 27 | int milliseconds = (int) (duration % MILLISECONDS_IN_A_SECOND); 28 | duration /= ONE_SECOND; 29 | int seconds = (int) (duration % SECONDS_IN_A_MINUTE); 30 | duration /= SECONDS_IN_A_MINUTE; 31 | int minutes = (int) (duration % MINUTES_IN_AN_HOUR); 32 | duration /= MINUTES_IN_AN_HOUR; 33 | int hours = (int) (duration % HOURS_IN_A_DAY); 34 | duration /= HOURS_IN_A_DAY; 35 | int days = (int) (duration % DAYS_IN_A_YEAR); 36 | duration /= DAYS_IN_A_YEAR; 37 | int years = (int) (duration); 38 | 39 | res = new TimeMap(milliseconds, seconds, minutes, hours, days, years); 40 | } 41 | return res; 42 | 43 | } 44 | } 45 | 46 | class TimeMap { 47 | public final int MSEC, SEC, MINUTES, HOURS, DAYS, YEARS; 48 | 49 | public TimeMap(int msec, int sec, int minutes, int hours, int days, int years) 50 | { 51 | MSEC = msec; 52 | SEC = sec; 53 | MINUTES = minutes; 54 | HOURS = hours; 55 | DAYS = days; 56 | YEARS = years; 57 | } 58 | } -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/ExceptionsServlet.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import freemarker.template.Configuration; 4 | import freemarker.template.TemplateException; 5 | import net.johnewart.gearman.engine.storage.ExceptionStorageEngine; 6 | import net.johnewart.gearman.engine.storage.NoopExceptionStorageEngine; 7 | 8 | import javax.servlet.ServletException; 9 | import javax.servlet.http.HttpServlet; 10 | import javax.servlet.http.HttpServletRequest; 11 | import javax.servlet.http.HttpServletResponse; 12 | import java.io.IOException; 13 | import java.io.OutputStream; 14 | import java.io.OutputStreamWriter; 15 | 16 | public class ExceptionsServlet extends HttpServlet { 17 | private final ExceptionStorageEngine exceptionStorageEngine; 18 | private static Configuration cfg = new Configuration(); 19 | 20 | public ExceptionsServlet(ExceptionStorageEngine exceptionStorageEngine) { 21 | this.exceptionStorageEngine = exceptionStorageEngine; 22 | } 23 | 24 | @Override 25 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException 26 | { 27 | cfg.setClassForTemplateLoading(ClusterServlet.class, "templates"); 28 | cfg.setTemplateUpdateDelay(0); 29 | 30 | final int pageSize, pageNum; 31 | if(req.getParameter("pageSize") != null) { 32 | pageSize = Integer.valueOf(req.getParameter("pageSize")).intValue(); 33 | } else { 34 | pageSize = 50; 35 | } 36 | 37 | if(req.getParameter("pageNum") != null) { 38 | pageNum = Integer.valueOf(req.getParameter("pageNum")).intValue(); 39 | } else { 40 | pageNum = 1; 41 | } 42 | 43 | try { 44 | final OutputStream output = resp.getOutputStream(); 45 | OutputStreamWriter wr = new OutputStreamWriter(output); 46 | 47 | if(exceptionStorageEngine != null && exceptionStorageEngine.getClass() != NoopExceptionStorageEngine.class) { 48 | cfg.getTemplate("exceptions.ftl").process(new ExceptionsView(exceptionStorageEngine, pageSize, pageNum), wr); 49 | } else { 50 | cfg.getTemplate("noexceptions.ftl").process(null, wr); 51 | } 52 | 53 | } catch (IOException ioe) { 54 | ioe.printStackTrace(); 55 | } catch (TemplateException e) { 56 | e.printStackTrace(); 57 | } 58 | 59 | } 60 | 61 | } 62 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/ExceptionsView.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import net.johnewart.gearman.engine.core.JobManager; 4 | import net.johnewart.gearman.engine.queue.JobQueue; 5 | import net.johnewart.gearman.engine.storage.ExceptionData; 6 | import net.johnewart.gearman.engine.storage.ExceptionStorageEngine; 7 | import net.johnewart.gearman.server.util.JobQueueMonitor; 8 | import net.johnewart.gearman.server.util.JobQueueSnapshot; 9 | import net.johnewart.gearman.server.util.SystemSnapshot; 10 | import org.joda.time.LocalDateTime; 11 | 12 | import java.net.UnknownHostException; 13 | import java.util.ArrayList; 14 | import java.util.Date; 15 | import java.util.List; 16 | import java.util.Map; 17 | 18 | public class ExceptionsView { 19 | protected final ExceptionStorageEngine exceptionStorageEngine; 20 | private final int pageSize; 21 | private final int pageNum; 22 | private final int exceptionCount; 23 | 24 | public ExceptionsView(ExceptionStorageEngine exceptionStorageEngine, int pageSize, int pageNum) 25 | { 26 | this.exceptionStorageEngine = exceptionStorageEngine; 27 | this.pageSize = pageSize; 28 | this.pageNum = pageNum; 29 | this.exceptionCount = exceptionStorageEngine.getCount(); 30 | } 31 | 32 | public int getPageSize() { 33 | return pageSize; 34 | } 35 | 36 | public int getPageNum() { 37 | return pageNum; 38 | } 39 | 40 | public int getPageCount() { 41 | return new Double(Math.ceil((double)exceptionCount / (double)pageSize)).intValue(); 42 | } 43 | 44 | public int getNextPageNumber() { 45 | return pageNum + 1; 46 | } 47 | 48 | public int getPreviousPageNumber() { 49 | return pageNum - 1; 50 | } 51 | 52 | public boolean hasNextPage() { 53 | return (pageNum * pageSize < exceptionCount); 54 | } 55 | 56 | public boolean hasPreviousPage() { 57 | return pageNum > 1; 58 | } 59 | 60 | public int getExceptionCount() { 61 | return exceptionCount; 62 | } 63 | 64 | public int getStart() { 65 | return ((pageNum - 1) * pageSize) + 1; 66 | } 67 | 68 | public int getEnd() { 69 | int end = pageNum * pageSize; 70 | return end > exceptionCount ? exceptionCount : end; 71 | } 72 | 73 | public List getExceptions() 74 | { 75 | return exceptionStorageEngine.getExceptions(pageNum, pageSize); 76 | } 77 | 78 | public String getJobHandle(ExceptionData data) { 79 | return data.jobHandle; 80 | } 81 | 82 | public String getUniqueId(ExceptionData data) { 83 | return data.uniqueId; 84 | } 85 | 86 | public String getJobDataString(ExceptionData data) { 87 | return new String(data.jobData); 88 | } 89 | 90 | public String getExceptionDataString(ExceptionData data) { 91 | return new String(data.exceptionData); 92 | } 93 | 94 | public String getDateTime(ExceptionData data) { 95 | return data.when.toString(); 96 | } 97 | } 98 | 99 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/JobQueueServlet.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.constants.JobPriority; 5 | import net.johnewart.gearman.engine.core.JobManager; 6 | import net.johnewart.gearman.engine.exceptions.EnqueueException; 7 | import net.johnewart.gearman.util.ByteArray; 8 | import org.slf4j.Logger; 9 | import org.slf4j.LoggerFactory; 10 | 11 | import javax.servlet.ServletException; 12 | import javax.servlet.http.HttpServlet; 13 | import javax.servlet.http.HttpServletRequest; 14 | import javax.servlet.http.HttpServletResponse; 15 | import java.io.IOException; 16 | import java.io.OutputStream; 17 | 18 | public class JobQueueServlet extends HttpServlet { 19 | private static final String CONTENT_TYPE = "application/json"; 20 | private final JobManager jobManager; 21 | private final Logger LOG = LoggerFactory.getLogger(JobQueueServlet.class); 22 | 23 | public JobQueueServlet(JobManager jobManager) 24 | { 25 | this.jobManager = jobManager; 26 | } 27 | 28 | @Override 29 | protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 30 | doPost(req, resp); 31 | } 32 | 33 | @Override 34 | protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException { 35 | final String jobQueueName = req.getPathInfo().replaceFirst("/", ""); 36 | final Job.Builder jobBuilder = new Job.Builder(); 37 | final JobPriority jobPriority = parsePriority(req.getParameter("priority")); 38 | final ByteArray data = new ByteArray(req.getParameter("data")); 39 | final String uniqueId = req.getParameter("uniqueId"); 40 | 41 | final Job job = 42 | jobBuilder.data(data.getBytes()) 43 | .functionName(jobQueueName) 44 | .background(true) 45 | .uniqueID(uniqueId) 46 | .priority(jobPriority) 47 | .build(); 48 | 49 | 50 | final Job created; 51 | try 52 | { 53 | created = jobManager.storeJob(job); 54 | resp.setStatus(HttpServletResponse.SC_OK); 55 | resp.setContentType(CONTENT_TYPE); 56 | 57 | final OutputStream output = resp.getOutputStream(); 58 | output.write(new ByteArray(created.getJobHandle()).getBytes()); 59 | } catch (EnqueueException e) { 60 | resp.sendError(500, e.getMessage()); 61 | } 62 | } 63 | 64 | 65 | private JobPriority parsePriority(final String priorityString) { 66 | 67 | JobPriority jobPriority = null; 68 | 69 | try { 70 | if (priorityString == null || priorityString.equals("")) { 71 | jobPriority = JobPriority.NORMAL; 72 | } else { 73 | jobPriority = JobPriority.valueOf(priorityString); 74 | } 75 | } catch (IllegalArgumentException iae) { 76 | LOG.warn("Invalid job queue priority: " + priorityString); 77 | } 78 | 79 | if (jobPriority == null) { 80 | jobPriority = JobPriority.NORMAL; 81 | } 82 | 83 | return jobPriority; 84 | 85 | } 86 | 87 | } 88 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/JobQueueStatusView.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import net.johnewart.gearman.engine.metrics.QueueMetrics; 4 | import net.johnewart.gearman.server.util.JobQueueMetrics; 5 | import net.johnewart.gearman.server.util.JobQueueMonitor; 6 | 7 | public class JobQueueStatusView extends StatusView { 8 | private final String jobQueueName; 9 | 10 | public JobQueueStatusView(final JobQueueMonitor jobQueueMonitor, 11 | final QueueMetrics queueMetrics, 12 | final String jobQueueName) 13 | { 14 | super(jobQueueMonitor, queueMetrics); 15 | this.jobQueueName = jobQueueName; 16 | } 17 | 18 | public String getJobQueueName() { 19 | return jobQueueName; 20 | } 21 | 22 | public JobQueueMetrics getJobQueueSnapshots() 23 | { 24 | return this.getJobQueueSnapshots(this.jobQueueName); 25 | } 26 | 27 | public Long getNumberOfConnectedWorkers() 28 | { 29 | return queueMetrics.getActiveWorkers(jobQueueName); 30 | } 31 | 32 | public Long getActiveJobCount() { 33 | return queueMetrics.getActiveJobCount(jobQueueName); 34 | } 35 | 36 | public long getEnqueuedJobCount() { 37 | return queueMetrics.getEnqueuedJobCount(jobQueueName); 38 | } 39 | 40 | public long getCompletedJobCount() { 41 | return queueMetrics.getCompletedJobCount(jobQueueName); 42 | } 43 | 44 | public long getFailedJobCount() { 45 | return queueMetrics.getFailedJobCount(jobQueueName); 46 | } 47 | 48 | public long getExceptionCount() { 49 | return queueMetrics.getExceptionCount(jobQueueName); 50 | } 51 | 52 | public long getRunningJobsCount() { 53 | return queueMetrics.getRunningJobsCount(jobQueueName); 54 | } 55 | 56 | public long getPendingJobsCount() { 57 | return queueMetrics.getPendingJobsCount(jobQueueName); 58 | } 59 | 60 | public long getHighPriorityJobsCount() { 61 | return queueMetrics.getHighPriorityJobsCount(jobQueueName); 62 | } 63 | 64 | public long getMidPriorityJobsCount() { 65 | return queueMetrics.getMidPriorityJobsCount(jobQueueName); 66 | } 67 | 68 | public long getLowPriorityJobsCount() { 69 | return queueMetrics.getLowPriorityJobsCount(jobQueueName); 70 | } 71 | 72 | } 73 | -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/NumberFormatter.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | public class NumberFormatter 4 | { 5 | public NumberFormatter() {} 6 | public String format(Number number) { 7 | long longVal = number.longValue(); 8 | if(longVal < 1000) 9 | { 10 | return number.toString(); 11 | } 12 | 13 | if (longVal < 1000000) 14 | { 15 | return String.format("~%.1fK", number.doubleValue() / 1000.0); 16 | } 17 | 18 | if (longVal < 1000000000) 19 | { 20 | return String.format("~%.2fM", number.doubleValue() / 1000000.0); 21 | } 22 | 23 | return String.format("~%.3fB", number.doubleValue() / 1000000000.0); 24 | } 25 | } -------------------------------------------------------------------------------- /gearman-server/src/main/java/net/johnewart/gearman/server/web/SystemStatusView.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.web; 2 | 3 | import net.johnewart.gearman.engine.metrics.QueueMetrics; 4 | import net.johnewart.gearman.server.util.SnapshottingJobQueueMonitor; 5 | 6 | public class SystemStatusView extends StatusView { 7 | 8 | public SystemStatusView(SnapshottingJobQueueMonitor jobQueueMonitor, QueueMetrics queueMetrics) 9 | { 10 | super(jobQueueMonitor, queueMetrics); 11 | } 12 | } 13 | -------------------------------------------------------------------------------- /gearman-server/src/main/resources/logback.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 5 | 6 | %d{HH:mm:ss.SSS} - [%thread] %-5level %logger{36} - %msg%n 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/cluster.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="net.johnewart.gearman.server.web.ClusterView" --> 2 | 3 | <#include "layout.ftl"> 4 | <@layout> 5 | Cluster Members 6 | 7 | 8 | ID 9 | Hostname 10 | Address 11 | 12 | <#list clusterMembers as member> 13 | 14 | ${member.uuid} 15 | ${member.getInetSocketAddress().hostName} 16 | ${member.getInetSocketAddress().address.hostAddress}:${member.getInetSocketAddress().port?c} 17 | 18 | #list> 19 | 20 | 21 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/css/admin.css: -------------------------------------------------------------------------------- 1 | table.grid { 2 | border: 1px solid #888; 3 | } 4 | table.grid th { 5 | background-color: #eee; 6 | border-bottom: 1px solid #888; 7 | border-right: 1px solid #888; 8 | border-collapse: collapse; 9 | } 10 | 11 | table.grid td { 12 | text-align: right; 13 | padding-right: 20px; 14 | } 15 | -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/exceptions.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="net.johnewart.gearman.server.web.ExceptionsView" --> 2 | 3 | <#include "layout.ftl"> 4 | <@layout> 5 | Exceptions 6 | Showing ${start}-${end} of ${exceptionCount} exceptions (page ${pageNum} of ${pageCount}) 7 | 8 | 9 | <#if hasNextPage()> 10 | Next Page 11 | #if> 12 | <#if hasPreviousPage()> 13 | Previous Page 14 | #if> 15 | 16 | 17 | 18 | 19 | Job Handle 20 | Unique ID 21 | Job data 22 | Exception data 23 | Date/Time 24 | 25 | <#list exceptions as exception> 26 | 27 | ${getJobHandle(exception)} 28 | ${getUniqueId(exception)} 29 | ${getJobDataString(exception)} 30 | ${getExceptionDataString(exception)} 31 | ${getDateTime(exception)} 32 | 33 | #list> 34 | 35 | 36 | 37 | 38 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/layout.ftl: -------------------------------------------------------------------------------- 1 | <#macro layout> 2 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | <#include "styles.ftl"> 23 | 24 | 25 | 26 | 27 | 28 | 29 | Dashboard 30 | Queues 31 | Cluster Status 32 | Exceptions 33 | 34 | 35 | 36 | <#nested> 37 | 38 | 39 | 40 | 41 | #macro> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/nocluster.ftl: -------------------------------------------------------------------------------- 1 | <#include "layout.ftl"> 2 | <@layout> 3 | Cluster Support Not Enabled 4 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/noexceptions.ftl: -------------------------------------------------------------------------------- 1 | <#include "layout.ftl"> 2 | <@layout> 3 | Exceptions Storage Not Enabled 4 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/queue.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="net.johnewart.gearman.server.web.JobQueueStatusView" --> 2 | 3 | <#include "layout.ftl"> 4 | <@layout> 5 | 6 | ${jobQueueName} 7 | 8 | ${numberOfConnectedWorkers} worker(s) 9 | 10 | 11 | Active 12 | Enqueued 13 | Completed 14 | Failed 15 | Exceptions 16 | High Queue 17 | Mid Queue 18 | Low Queue 19 | 20 | 21 | ${activeJobCount} 22 | ${enqueuedJobCount} 23 | ${completedJobCount} 24 | ${failedJobCount} 25 | ${exceptionCount} 26 | ${highPriorityJobsCount} 27 | ${midPriorityJobsCount} 28 | ${lowPriorityJobsCount} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 50 | 51 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/queues.ftl: -------------------------------------------------------------------------------- 1 | <#-- @ftlvariable name="" type="net.johnewart.gearman.server.web.StatusView" --> 2 | 3 | <#include "layout.ftl"> 4 | <@layout> 5 | 6 | ${jobQueueCount} Queues 7 | 8 | <#list jobQueues as jobQueue> 9 | 10 | ${jobQueue!"N/A"} 11 | 12 | 13 | 14 | 28 | 29 | #list> 30 | 31 | 32 | @layout> -------------------------------------------------------------------------------- /gearman-server/src/main/resources/net/johnewart/gearman/server/web/templates/rickshaw.extensions.js: -------------------------------------------------------------------------------- 1 | var RenderControls = function(args) { 2 | 3 | this.initialize = function() { 4 | 5 | this.element = args.element; 6 | this.graph = args.graph; 7 | this.settings = this.serialize(); 8 | 9 | this.inputs = { 10 | renderer: this.element.elements.renderer, 11 | interpolation: this.element.elements.interpolation, 12 | offset: this.element.elements.offset 13 | }; 14 | 15 | this.element.addEventListener('change', function(e) { 16 | 17 | this.settings = this.serialize(); 18 | 19 | if (e.target.name == 'renderer') { 20 | this.setDefaultOffset(e.target.value); 21 | } 22 | 23 | this.syncOptions(); 24 | this.settings = this.serialize(); 25 | 26 | var config = { 27 | renderer: this.settings.renderer, 28 | interpolation: this.settings.interpolation 29 | }; 30 | 31 | if (this.settings.offset == 'value') { 32 | config.unstack = true; 33 | config.offset = 'zero'; 34 | } else if (this.settings.offset == 'expand') { 35 | config.unstack = false; 36 | config.offset = this.settings.offset; 37 | } else { 38 | config.unstack = false; 39 | config.offset = this.settings.offset; 40 | } 41 | 42 | this.graph.configure(config); 43 | this.graph.render(); 44 | 45 | }.bind(this), false); 46 | } 47 | 48 | this.serialize = function() { 49 | 50 | var values = {}; 51 | var pairs = $(this.element).serializeArray(); 52 | 53 | pairs.forEach( function(pair) { 54 | values[pair.name] = pair.value; 55 | } ); 56 | 57 | return values; 58 | }; 59 | 60 | this.syncOptions = function() { 61 | 62 | var options = this.rendererOptions[this.settings.renderer]; 63 | 64 | Array.prototype.forEach.call(this.inputs.interpolation, function(input) { 65 | 66 | if (options.interpolation) { 67 | input.disabled = false; 68 | input.parentNode.classList.remove('disabled'); 69 | } else { 70 | input.disabled = true; 71 | input.parentNode.classList.add('disabled'); 72 | } 73 | }); 74 | 75 | Array.prototype.forEach.call(this.inputs.offset, function(input) { 76 | 77 | if (options.offset.filter( function(o) { return o == input.value } ).length) { 78 | input.disabled = false; 79 | input.parentNode.classList.remove('disabled'); 80 | 81 | } else { 82 | input.disabled = true; 83 | input.parentNode.classList.add('disabled'); 84 | } 85 | 86 | }.bind(this)); 87 | 88 | }; 89 | 90 | this.setDefaultOffset = function(renderer) { 91 | 92 | var options = this.rendererOptions[renderer]; 93 | 94 | if (options.defaults && options.defaults.offset) { 95 | 96 | Array.prototype.forEach.call(this.inputs.offset, function(input) { 97 | if (input.value == options.defaults.offset) { 98 | input.checked = true; 99 | } else { 100 | input.checked = false; 101 | } 102 | 103 | }.bind(this)); 104 | } 105 | }; 106 | 107 | this.rendererOptions = { 108 | 109 | area: { 110 | interpolation: true, 111 | offset: ['zero', 'wiggle', 'expand', 'value'], 112 | defaults: { offset: 'zero' } 113 | }, 114 | line: { 115 | interpolation: true, 116 | offset: ['expand', 'value'], 117 | defaults: { offset: 'value' } 118 | }, 119 | bar: { 120 | interpolation: false, 121 | offset: ['zero', 'wiggle', 'expand', 'value'], 122 | defaults: { offset: 'zero' } 123 | }, 124 | scatterplot: { 125 | interpolation: false, 126 | offset: ['value'], 127 | defaults: { offset: 'value' } 128 | } 129 | }; 130 | 131 | this.initialize(); 132 | }; 133 | 134 | -------------------------------------------------------------------------------- /gearman-server/src/test/java/net/johnewart/gearman/server/JobFactory.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server; 2 | 3 | import net.johnewart.gearman.common.Job; 4 | import net.johnewart.gearman.common.interfaces.JobHandleFactory; 5 | import net.johnewart.gearman.constants.JobPriority; 6 | import net.johnewart.gearman.engine.util.LocalJobHandleFactory; 7 | import org.joda.time.DateTime; 8 | import org.joda.time.Seconds; 9 | 10 | import java.util.UUID; 11 | 12 | public class JobFactory { 13 | private static final JobHandleFactory jobHandleFactory = 14 | new LocalJobHandleFactory("testhost"); 15 | 16 | public static Job generateForegroundJob(String functionName) 17 | { 18 | String uuid = UUID.randomUUID().toString(); 19 | byte[] data = {'f','o','o'}; 20 | JobPriority priority = JobPriority.NORMAL; 21 | boolean isBackground = false; 22 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 23 | } 24 | 25 | public static Job generateBackgroundJob(String functionName) 26 | { 27 | String uuid = UUID.randomUUID().toString(); 28 | byte[] data = {'b','a','r'}; 29 | JobPriority priority = JobPriority.NORMAL; 30 | boolean isBackground = true; 31 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 32 | } 33 | 34 | public static Job generateFutureJob(String functionName, Seconds seconds) { 35 | String uuid = UUID.randomUUID().toString(); 36 | byte[] data = {'f','l','u','x',' ','c','a','p'}; 37 | JobPriority priority = JobPriority.NORMAL; 38 | boolean isBackground = true; 39 | long whenToRun = new DateTime().plus(seconds).toDate().getTime() / 1000; 40 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, whenToRun); 41 | } 42 | 43 | public static Job generateHighPriorityBackgroundJob(String functionName) 44 | { 45 | String uuid = UUID.randomUUID().toString(); 46 | byte[] data = {'s','u','p','e','r'}; 47 | JobPriority priority = JobPriority.HIGH; 48 | boolean isBackground = true; 49 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); } 50 | 51 | public static Job generateLowPriorityBackgroundJob(String functionName) 52 | { 53 | String uuid = UUID.randomUUID().toString(); 54 | byte[] data = {'s','u','p','e','r'}; 55 | JobPriority priority = JobPriority.LOW; 56 | boolean isBackground = true; 57 | return new Job(functionName, uuid, data, jobHandleFactory.getNextJobHandle(), priority, isBackground, -1); 58 | } 59 | } 60 | 61 | -------------------------------------------------------------------------------- /gearman-server/src/test/java/net/johnewart/gearman/server/cluster/util/HazelcastJobHandleFactoryTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.cluster.util; 2 | 3 | import com.hazelcast.core.HazelcastInstance; 4 | import com.hazelcast.core.IAtomicLong; 5 | import org.junit.Test; 6 | 7 | import static org.hamcrest.core.Is.is; 8 | import static org.junit.Assert.assertThat; 9 | import static org.mockito.Matchers.anyString; 10 | import static org.mockito.Mockito.mock; 11 | import static org.mockito.Mockito.when; 12 | 13 | public class HazelcastJobHandleFactoryTest { 14 | 15 | @Test 16 | public void shouldIncrementCounter() { 17 | 18 | IAtomicLong mockAtomicLong = mock(IAtomicLong.class); 19 | when(mockAtomicLong.incrementAndGet()).thenReturn(1L); 20 | 21 | HazelcastInstance mockHazelcast = mock(HazelcastInstance.class); 22 | when(mockHazelcast.getAtomicLong(anyString())).thenReturn(mockAtomicLong); 23 | 24 | HazelcastJobHandleFactory hazelcastJobHandleFactory = new HazelcastJobHandleFactory(mockHazelcast, "localhost"); 25 | 26 | assertThat("Generates a proper job handle", 27 | new String(hazelcastJobHandleFactory.getNextJobHandle()), 28 | is("H:localhost:1")); 29 | } 30 | 31 | 32 | } 33 | -------------------------------------------------------------------------------- /gearman-server/src/test/java/net/johnewart/gearman/server/net/DecoderTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import static org.hamcrest.core.Is.is; 4 | import static org.junit.Assert.assertThat; 5 | import static org.mockito.Matchers.any; 6 | import static org.mockito.Matchers.anyInt; 7 | import static org.mockito.Mockito.mock; 8 | import static org.mockito.Mockito.spy; 9 | import static org.mockito.Mockito.when; 10 | 11 | import java.util.LinkedList; 12 | import java.util.List; 13 | import java.util.concurrent.atomic.AtomicInteger; 14 | 15 | import net.johnewart.gearman.server.net.Decoder; 16 | import org.junit.Test; 17 | import org.mockito.invocation.InvocationOnMock; 18 | import org.mockito.stubbing.Answer; 19 | 20 | import io.netty.buffer.ByteBuf; 21 | import io.netty.channel.ChannelHandlerContext; 22 | import net.johnewart.gearman.common.packets.Packet; 23 | import net.johnewart.gearman.common.packets.request.EchoRequest; 24 | import net.johnewart.gearman.constants.PacketType; 25 | 26 | public class DecoderTest { 27 | @Test 28 | public void decodeBinaryPacket() throws Exception { 29 | Decoder d = spy(new Decoder()); 30 | ByteBuf mockBuffer = mock(ByteBuf.class); 31 | ChannelHandlerContext mockCtx = mock(ChannelHandlerContext.class); 32 | List decodedObjects = new LinkedList<>(); 33 | 34 | EchoRequest echoPacket = new EchoRequest("OHAI"); 35 | byte zeroByte = 0; 36 | final byte[] packetData = echoPacket.toByteArray(); 37 | 38 | when(mockBuffer.readByte()).thenReturn(zeroByte); 39 | when(mockBuffer.readBytes(any(byte[].class), anyInt(), anyInt())).then(new Answer() { 40 | @Override 41 | public Object answer(InvocationOnMock invocationOnMock) throws Throwable { 42 | byte[] buf = (byte[]) invocationOnMock.getArguments()[0]; 43 | int offset = (Integer) invocationOnMock.getArguments()[1]; 44 | int size = (Integer) invocationOnMock.getArguments()[2]; 45 | for(int i = 0; i < size; i++) { 46 | buf[offset+i] = packetData[offset+i]; 47 | } 48 | return null; 49 | } 50 | }); 51 | 52 | d.decode(mockCtx, mockBuffer, decodedObjects); 53 | 54 | assertThat(decodedObjects.size(), is(1)); 55 | Packet p = (Packet)decodedObjects.get(0); 56 | assertThat(p.getType(), is(PacketType.ECHO_REQ)); 57 | } 58 | 59 | @Test 60 | public void decodeTextPacket() throws Exception { 61 | Decoder d = spy(new Decoder()); 62 | ByteBuf mockBuffer = mock(ByteBuf.class); 63 | ChannelHandlerContext mockCtx = mock(ChannelHandlerContext.class); 64 | List decodedObjects = new LinkedList<>(); 65 | 66 | final byte[] commandMessage = {'S','T','A','T','U','S',10}; 67 | 68 | final AtomicInteger byteCounter = new AtomicInteger(0); 69 | when(mockBuffer.readByte()).thenAnswer(new Answer() { 70 | @Override 71 | public Object answer(InvocationOnMock invocationOnMock) throws Throwable { 72 | return commandMessage[byteCounter.getAndIncrement()]; 73 | } 74 | }); 75 | 76 | d.decode(mockCtx, mockBuffer, decodedObjects); 77 | 78 | assertThat(decodedObjects.size(), is(1)); 79 | String command = (String)decodedObjects.get(0); 80 | assertThat(command, is("STATUS")); 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /gearman-server/src/test/java/net/johnewart/gearman/server/net/EncoderTest.java: -------------------------------------------------------------------------------- 1 | package net.johnewart.gearman.server.net; 2 | 3 | import net.johnewart.gearman.common.packets.Packet; 4 | import net.johnewart.gearman.common.packets.request.EchoRequest; 5 | import net.johnewart.gearman.server.net.Encoder; 6 | import org.junit.Test; 7 | 8 | import java.util.Arrays; 9 | 10 | import static junit.framework.Assert.assertTrue; 11 | 12 | public class EncoderTest { 13 | @Test 14 | public void encodesPacketProperly() 15 | { 16 | Packet p = new EchoRequest("ok"); 17 | byte[] channelDataBytes = Encoder.encodePacket(p); 18 | assertTrue(Arrays.equals(p.toByteArray(), channelDataBytes)); 19 | } 20 | 21 | @Test 22 | public void encodesStringProperly() 23 | { 24 | String stringToEncode = "gearman"; 25 | byte[] channelDataBytes = Encoder.encodeString(stringToEncode); 26 | assertTrue(Arrays.equals(stringToEncode.getBytes(), channelDataBytes)); 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /misc/dashboard.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnewart/gearman-java/7181f71a7065408c1fce90e7724177b7080933b5/misc/dashboard.jpg -------------------------------------------------------------------------------- /misc/queue.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnewart/gearman-java/7181f71a7065408c1fce90e7724177b7080933b5/misc/queue.jpg -------------------------------------------------------------------------------- /misc/queues.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/johnewart/gearman-java/7181f71a7065408c1fce90e7724177b7080933b5/misc/queues.jpg --------------------------------------------------------------------------------
9 | <#if hasNextPage()> 10 | Next Page 11 | #if> 12 | <#if hasPreviousPage()> 13 | Previous Page 14 | #if> 15 |