Skip to content

Commit

Permalink
Added caching for jobs finaaallly (#109)
Browse files Browse the repository at this point in the history
  • Loading branch information
ShimaaBetah authored May 19, 2024
1 parent 1f9fcdb commit 3aa7d5c
Show file tree
Hide file tree
Showing 20 changed files with 92 additions and 16 deletions.
1 change: 1 addition & 0 deletions services/jobs/.env
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
JOBS_DB_URL=jobs_db:9042
JOBS_MQ_URL=service_mq
REDIS_URL=service_redis
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

@SpringBootApplication
@EnableAsync
@EnableCaching
public class JobsApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -73,9 +73,10 @@ public AcceptProposalResponse Run(AcceptProposalRequest request) {
.build();
}
acceptedJob.setActive(false);
acceptedJob.setSearchIndex(null);
String contractId = initiateContract(acceptedProposal, acceptedJob, request);
proposalRepository.save(acceptedProposal);
jobRepository.save(acceptedJob);
String contractId = initiateContract(acceptedProposal, acceptedJob, request);
logger.info("[x] Contract Initiated with id" + contractId);
return AcceptProposalResponse.builder()
.withStatusCode(HttpStatusCode.OK)
Expand All @@ -89,7 +90,7 @@ public AcceptProposalResponse Run(AcceptProposalRequest request) {
.withContractId(contractId)
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while accepting job proposal", e.getMessage());
logger.error("[x] An error occurred while accepting job proposal" + e.getMessage());
return AcceptProposalResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while accepting job proposal")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public CreateJobResponse Run(CreateJobRequest request) {
.withJobId(savedJob.getId().toString())
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while saving job", e.getMessage());
logger.error("[x] An error occurred while saving job" + e.getMessage());
return CreateJobResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while saving job")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -76,7 +76,7 @@ public CreateProposalResponse Run(CreateProposalRequest request) {
.withId(savedProposal.getPrimaryKey().getId().toString())
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while saving proposal", e.getMessage());
logger.error("[x] An error occurred while saving proposal" + e.getMessage());
return CreateProposalResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while saving proposal")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ public GetJobByIdResponse Run(GetJobByIdRequest request) {
.withSkills(job.get().getSkills())
.withExperience(job.get().getExperienceLevel())
.withClientId(job.get().getClientId())
.withIsActive(job.get().isActive())
.withActive(job.get().isActive())
.withBudget(job.get().getBudget())
.withCreatedAt(job.get().getCreatedAt())
.withModifiedAt(job.get().getUpdatedAt())
Expand All @@ -43,7 +43,7 @@ public GetJobByIdResponse Run(GetJobByIdRequest request) {
.build();
}
} catch (Exception e) {
logger.error("[x] An error occurred while fetching job", e.getMessage());
logger.error("[x] An error occurred while fetching job" + e.getMessage());

return GetJobByIdResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,7 +35,7 @@ public GetMyJobsResponse Run(GetMyJobsRequest request) {
.withStatusCode(HttpStatusCode.OK)
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while fetching jobs", e.getMessage());
logger.error("[x] An error occurred while fetching jobs" + e.getMessage());
return GetMyJobsResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while fetching jobs")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ public GetMyProposalsResponse Run(GetMyProposalsRequest request) {
.withStatusCode(HttpStatusCode.OK)
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while fetching proposals", e.getMessage());
logger.error("[x] An error occurred while fetching proposals" + e.getMessage());
return GetMyProposalsResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while fetching proposals")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public GetProposalsByJobIdResponse Run(GetProposalsByJobIdRequest request) {
.withStatusCode(HttpStatusCode.OK)
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while fetching proposals", e.getMessage());
logger.error("[x] An error occurred while fetching proposals" + e.getMessage());
return GetProposalsByJobIdResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage("An error occurred while fetching proposals")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ public SearchJobsResponse Run(SearchJobsRequest request) {
.withStatusCode(HttpStatusCode.OK)
.build();
} catch (Exception e) {
logger.error("[x] An error occurred while searching for jobs", e.getMessage());
logger.error("[x] An error occurred while searching for jobs" + e.getMessage());
return SearchJobsResponse.builder()
.withStatusCode(HttpStatusCode.INTERNAL_SERVER_ERROR)
.withErrorMessage(e.getMessage())
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.workup.jobs.config;

import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;

@Configuration
@Import(com.workup.shared.redis.RedisConfig.class)
public class RedisConfig {}
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package com.workup.jobs.models;

import java.io.Serializable;
import lombok.Builder;
import lombok.Getter;
import org.springframework.data.cassandra.core.mapping.UserDefinedType;

@Getter
@Builder(setterPrefix = "with")
@UserDefinedType
public class Attachment {
public class Attachment implements Serializable {

private String url;
private String name;
Expand Down
4 changes: 3 additions & 1 deletion services/jobs/src/main/java/com/workup/jobs/models/Job.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package com.workup.jobs.models;

import com.workup.shared.enums.jobs.Experience;
import java.io.Serializable;
import java.util.Date;
import java.util.UUID;
import lombok.Builder;
Expand All @@ -17,7 +18,7 @@
@Getter
@Builder(setterPrefix = "with")
@Table("jobs")
public class Job {
public class Job implements Serializable {

@PrimaryKey private UUID id;

Expand All @@ -28,6 +29,7 @@ public class Job {

@SASI(indexMode = IndexMode.CONTAINS)
@Column("search_index")
@Setter
private String searchIndex;

@CassandraType(type = CassandraType.Name.LIST, typeArguments = CassandraType.Name.TEXT)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.workup.jobs.models;

import java.io.Serializable;
import java.util.Date;
import lombok.Builder;
import lombok.Getter;
Expand All @@ -8,7 +9,7 @@
@Getter
@Builder(setterPrefix = "with")
@UserDefinedType
public class Milestone {
public class Milestone implements Serializable {

private String description;
private Date dueDate;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

import com.workup.shared.commands.jobs.proposals.JobDuration;
import com.workup.shared.commands.jobs.proposals.ProposalStatus;
import java.io.Serializable;
import java.util.Date;
import java.util.List;
import java.util.UUID;
Expand All @@ -20,7 +21,7 @@
@Getter
@Builder(setterPrefix = "with")
@Table("proposals")
public class Proposal {
public class Proposal implements Serializable {

@PrimaryKey private Proposal.ProposalPrimaryKey primaryKey;

Expand Down Expand Up @@ -51,7 +52,7 @@ public class Proposal {
@PrimaryKeyClass
@Builder(setterPrefix = "with")
@Getter
public static class ProposalPrimaryKey {
public static class ProposalPrimaryKey implements Serializable {

@PrimaryKeyColumn(name = "job_id", ordinal = 0, type = PrimaryKeyType.PARTITIONED)
private String jobId;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@

import com.workup.jobs.models.Job;
import java.util.List;
import java.util.Optional;
import java.util.UUID;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;
import org.springframework.data.domain.Pageable;
Expand All @@ -14,4 +17,10 @@ public interface JobRepository extends CassandraRepository<Job, UUID> {

@Query("SELECT * FROM jobs_data.jobs WHERE client_id = ?0")
public List<Job> getJobsByClientId(String clientId);

@Cacheable(value = "jobs", key = "#jobId")
public Optional<Job> findById(UUID jobId);

@CacheEvict(value = "jobs", key = "#entity.id")
<S extends Job> S save(S entity);
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,20 @@

import com.workup.jobs.models.Proposal;
import java.util.List;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.cassandra.repository.CassandraRepository;
import org.springframework.data.cassandra.repository.Query;

public interface ProposalRepository
extends CassandraRepository<Proposal, Proposal.ProposalPrimaryKey> {
@Query("SELECT * FROM jobs_data.proposals WHERE job_id = ?0")
@Cacheable(value = "proposals", key = "#jobId")
public List<Proposal> findByJobId(String jobId);

@Query("SELECT * FROM jobs_data.proposals WHERE freelancer_id = ?0")
public List<Proposal> findByFreelancerId(String freelancerId);

@CacheEvict(value = "proposals", key = "#entity.primaryKey.jobId")
<S extends Proposal> S save(S entity);
}
5 changes: 5 additions & 0 deletions services/jobs/src/main/resources/application.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,8 @@ spring.cassandra.local-datacenter=datacenter1
spring.cassandra.keyspace-name=jobs_data
spring.cassandra.contact-points=${JOBS_DB_URL}
spring.cassandra.schema-action=CREATE_IF_NOT_EXISTS

spring.cache.type=redis
spring.cache.host=${REDIS_URL}
spring.cache.port=6379
spring.cache.redis.time-to-live=60000
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,10 @@
import com.workup.shared.commands.jobs.proposals.responses.AcceptProposalResponse;
import com.workup.shared.commands.jobs.proposals.responses.CreateProposalResponse;
import com.workup.shared.commands.jobs.requests.CreateJobRequest;
import com.workup.shared.commands.jobs.requests.GetJobByIdRequest;
import com.workup.shared.commands.jobs.requests.SearchJobsRequest;
import com.workup.shared.commands.jobs.responses.CreateJobResponse;
import com.workup.shared.commands.jobs.responses.GetJobByIdResponse;
import com.workup.shared.commands.jobs.responses.SearchJobsResponse;
import com.workup.shared.enums.HttpStatusCode;
import com.workup.shared.enums.ServiceQueueNames;
Expand All @@ -36,6 +38,7 @@
import org.springframework.test.context.DynamicPropertyRegistry;
import org.springframework.test.context.DynamicPropertySource;
import org.testcontainers.containers.CassandraContainer;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.containers.RabbitMQContainer;
import org.testcontainers.junit.jupiter.Container;
import org.testcontainers.junit.jupiter.Testcontainers;
Expand All @@ -56,6 +59,10 @@ static String GetCassandraContactPoint() {
return cassandraContainer.getHost() + ":" + cassandraContainer.getFirstMappedPort();
}

@Container
static final GenericContainer redisContainer =
new GenericContainer("redis:7.2.4").withExposedPorts(6379);

@DynamicPropertySource
static void datasourceProperties(DynamicPropertyRegistry registry) {
registry.add("spring.cassandra.contact-points", JobsApplicationTests::GetCassandraContactPoint);
Expand All @@ -64,6 +71,8 @@ static void datasourceProperties(DynamicPropertyRegistry registry) {
registry.add("spring.rabbitmq.port", rabbitMQContainer::getFirstMappedPort);
registry.add("spring.rabbitmq.username", rabbitMQContainer::getAdminUsername);
registry.add("spring.rabbitmq.password", rabbitMQContainer::getAdminPassword);
registry.add("spring.cache.host", redisContainer::getHost);
registry.add("spring.cache.port", redisContainer::getFirstMappedPort);
}

private static final String CLIENT_ONE_ID = "123";
Expand Down Expand Up @@ -106,6 +115,36 @@ void testCreateJob() {
() -> new RuntimeException("Job not found"));
}

@Test
void testGetJobById() {
Job job =
jobRepository.save(
Job.builder()
.withId(UUID.randomUUID())
.withTitle("Convert HTML Template to React 3")
.withDescription(
"I have an HTML template that I have purchased and own the rights to. I would"
+ " like it converted into a React application.")
.withSkills(new String[] {"HTML", "CSS", "JavaScript", "React"})
.withClientId(CLIENT_ONE_ID)
.withIsActive(true)
.build());

GetJobByIdResponse response =
(GetJobByIdResponse)
template.convertSendAndReceive(
ServiceQueueNames.JOBS,
GetJobByIdRequest.builder().withJobId(job.getId().toString()).build());

assertNotNull(response);
assertTrue(response.getStatusCode() == HttpStatusCode.OK);
assertEquals(job.getId().toString(), response.getId());
assertEquals(job.getTitle(), response.getTitle());
assertEquals(job.getDescription(), response.getDescription());
assertEquals(job.getClientId(), response.getClientId());
assertEquals(true, response.isActive());
}

/**
* Creates a proposal for a given a job ID.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ public class GetJobByIdResponse extends CommandResponse {
private final String[] skills;
private final Experience experience;
private final String clientId;
private final boolean isActive;
private final boolean active;
private final Date createdAt;
private final Date modifiedAt;
}

0 comments on commit 3aa7d5c

Please sign in to comment.