Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 13 additions & 0 deletions Account-Service/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,14 @@
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-starter-openfeign</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-cache</artifactId>
</dependency>
<dependency>
<groupId>com.github.ben-manes.caffeine</groupId>
<artifactId>caffeine</artifactId>
</dependency>

<dependency>
<groupId>org.springframework.boot</groupId>
Expand All @@ -64,6 +72,11 @@
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<scope>runtime</scope>
</dependency>
</dependencies>
<dependencyManagement>
<dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,12 @@

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.cloud.openfeign.EnableFeignClients;

@SpringBootApplication
@EnableFeignClients
@EnableCaching
public class AccountServiceApplication {

public static void main(String[] args) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

import java.util.List;

@FeignClient(name = "transaction-service", configuration = FeignConfiguration.class)
@FeignClient(name = "transaction-service", url = "http://localhost:8082", configuration = FeignConfiguration.class)
public interface TransactionService {

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.training.account.service.exception.*;
Expand Down Expand Up @@ -162,6 +163,7 @@ public String getBalance(String accountNumber) {
* @return A list of transaction responses
*/
@Override
@Cacheable(value = "transactions", key = "#accountId")
public List<TransactionResponse> getTransactionsFromAccountId(String accountId) {

return transactionService.getTransactionsFromAccountId(accountId);
Expand Down Expand Up @@ -213,4 +215,4 @@ public AccountDto readAccountByUserId(Long userId) {
return accountDto;
}).orElseThrow(ResourceNotFound::new);
}
}
}
29 changes: 21 additions & 8 deletions Account-Service/src/main/resources/application.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,17 +7,30 @@ spring:
not_found: 404

datasource:
url: jdbc:mysql://localhost:3306/account_service
username: root
password: root
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password

jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: update
show-sql: true
properties:
hibernate:
format_sql: true
ddl-auto: create-drop
show-sql: false

cache:
type: caffeine
caffeine:
spec: maximumSize=1000,expireAfterWrite=5m
cache-names:
- transactions

server:
port: 8081

# Direct URL configuration for Feign clients
feign:
client:
config:
transaction-service:
url: http://localhost:8082
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
package org.training.account.service;

import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.test.context.ActiveProfiles;
import org.training.account.service.external.TransactionService;
import org.training.account.service.model.dto.external.TransactionResponse;
import org.training.account.service.service.AccountService;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.Arrays;
import java.util.List;

import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.when;

@SpringBootTest
@ActiveProfiles("test")
public class CachePerformanceTest {

@Autowired
private AccountService accountService;

@MockBean
private TransactionService transactionService;

@Test
public void testTransactionCachePerformance() {
String testAccountId = "TEST_ACCOUNT_001";

List<TransactionResponse> mockTransactions = Arrays.asList(
TransactionResponse.builder()
.referenceId("TXN001")
.accountId(testAccountId)
.transactionType("DEPOSIT")
.amount(BigDecimal.valueOf(1000))
.localDateTime(LocalDateTime.now())
.transactionStatus("COMPLETED")
.comments("Test transaction")
.build()
);

when(transactionService.getTransactionsFromAccountId(anyString()))
.thenAnswer(invocation -> {
Thread.sleep(100);
return mockTransactions;
});

System.out.println("=== Cache Performance Test ===");

long startTime1 = System.currentTimeMillis();
List<TransactionResponse> transactions1 = accountService.getTransactionsFromAccountId(testAccountId);
long endTime1 = System.currentTimeMillis();
long firstCallTime = endTime1 - startTime1;

System.out.println("First call (cache miss): " + firstCallTime + "ms");
System.out.println("Transactions found: " + (transactions1 != null ? transactions1.size() : 0));

long startTime2 = System.currentTimeMillis();
List<TransactionResponse> transactions2 = accountService.getTransactionsFromAccountId(testAccountId);
long endTime2 = System.currentTimeMillis();
long secondCallTime = endTime2 - startTime2;

System.out.println("Second call (cache hit): " + secondCallTime + "ms");
System.out.println("Transactions found: " + (transactions2 != null ? transactions2.size() : 0));

if (firstCallTime > 0) {
double improvement = ((double)(firstCallTime - secondCallTime) / firstCallTime) * 100;
System.out.println("Performance improvement: " + String.format("%.1f", improvement) + "%");

if (improvement > 90) {
System.out.println("✅ Cache performance target achieved (>90% improvement)");
} else if (improvement > 50) {
System.out.println("⚠️ Cache working but improvement below target (<90%)");
} else {
System.out.println("❌ Cache may not be working effectively");
}
}

long startTime3 = System.currentTimeMillis();
List<TransactionResponse> transactions3 = accountService.getTransactionsFromAccountId(testAccountId);
long endTime3 = System.currentTimeMillis();
long thirdCallTime = endTime3 - startTime3;

System.out.println("Third call (cache hit): " + thirdCallTime + "ms");
System.out.println("=== Test Complete ===");
}
}
39 changes: 39 additions & 0 deletions Account-Service/src/test/resources/application-test.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
spring:
application:
name: account-service-test
ok: 200
not_found: 404
bad_request: 400
conflict: 409

datasource:
url: jdbc:h2:mem:testdb
driver-class-name: org.h2.Driver
username: sa
password: password

jpa:
database-platform: org.hibernate.dialect.H2Dialect
hibernate:
ddl-auto: create-drop
show-sql: false

cache:
type: caffeine
caffeine:
spec: maximumSize=100,expireAfterWrite=1m
cache-names:
- transactions

# Mock external services for testing
feign:
client:
config:
default:
connectTimeout: 5000
readTimeout: 5000

logging:
level:
org.training.account.service: DEBUG
org.springframework.cache: DEBUG
68 changes: 68 additions & 0 deletions test-cache-performance.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
#!/bin/bash

echo "=== Cache Performance Testing Script ==="
echo "This script will test the cache implementation by making HTTP requests"
echo

ACCOUNT_ID="ACC0000001"
BASE_URL="http://localhost:8081"
ENDPOINT="/accounts/${ACCOUNT_ID}/transactions"

echo "Testing endpoint: ${BASE_URL}${ENDPOINT}"
echo

make_request() {
local request_num=$1
echo "Request #${request_num}:"

start_time=$(date +%s%3N)
response=$(curl -s -w "%{http_code}" -o /tmp/response_${request_num}.json "${BASE_URL}${ENDPOINT}")
end_time=$(date +%s%3N)

duration=$((end_time - start_time))

if [ "$response" = "200" ]; then
transaction_count=$(cat /tmp/response_${request_num}.json | jq '. | length' 2>/dev/null || echo "unknown")
echo " ✅ Success (${duration}ms) - Transactions: ${transaction_count}"
else
echo " ❌ Failed (HTTP ${response}) - Time: ${duration}ms"
fi

echo " Response time: ${duration}ms"
return $duration
}

echo "Making 5 consecutive requests to test cache performance..."
echo

times=()
for i in {1..5}; do
make_request $i
times+=($?)
echo
sleep 1
done

echo "=== Performance Analysis ==="
echo "Request times: ${times[@]}ms"

if [ ${#times[@]} -ge 2 ]; then
first_time=${times[0]}
second_time=${times[1]}

if [ $first_time -gt 0 ]; then
improvement=$(( (first_time - second_time) * 100 / first_time ))
echo "Performance improvement from 1st to 2nd request: ${improvement}%"

if [ $improvement -gt 90 ]; then
echo "✅ Cache performance target achieved (>90% improvement)"
elif [ $improvement -gt 50 ]; then
echo "⚠️ Cache working but improvement below target"
else
echo "❌ Cache may not be working effectively"
fi
fi
fi

echo
echo "=== Test Complete ==="