Fixes according PR comments. Mainly Readme edits.

This commit is contained in:
Victor Zalevskii 2021-10-06 15:34:04 +03:00
parent 2a01563d21
commit c459b92933
5 changed files with 88 additions and 64 deletions

View File

@ -43,39 +43,29 @@ Wikipedia says:
**Programmatic Example** **Programmatic Example**
Let's first look at the data layer of our application. The interesting classes are `UserAccount` Let's first look at the data layer of our application. The interesting classes are `UserAccount`
which is a simple Java object containing the user account details, and `DbManager` which handles which is a simple Java object containing the user account details, and `DbManager` interface which handles
reading and writing of these objects to/from MongoDB database. reading and writing of these objects to/from database.
```java ```java
@Setter @Data
@Getter
@AllArgsConstructor @AllArgsConstructor
@ToString @ToString
@EqualsAndHashCode
public class UserAccount { public class UserAccount {
private String userId; private String userId;
private String userName; private String userName;
private String additionalInfo; private String additionalInfo;
} }
@Slf4j public interface DbManager {
public final class DbManager {
private static MongoClient mongoClient; void connect();
private static MongoDatabase db; void disconnect();
private DbManager() { /*...*/ } UserAccount readFromDb(String userId);
UserAccount writeToDb(UserAccount userAccount);
public static void createVirtualDb() { /*...*/ } UserAccount updateDb(UserAccount userAccount);
UserAccount upsertDb(UserAccount userAccount);
public static void connect() throws ParseException { /*...*/ }
public static UserAccount readFromDb(String userId) { /*...*/ }
public static void writeToDb(UserAccount userAccount) { /*...*/ }
public static void updateDb(UserAccount userAccount) { /*...*/ }
public static void upsertDb(UserAccount userAccount) { /*...*/ }
} }
``` ```
@ -171,30 +161,43 @@ strategies.
@Slf4j @Slf4j
public class CacheStore { public class CacheStore {
private static final int CAPACITY = 3;
private static LruCache cache; private static LruCache cache;
private final DbManager dbManager;
/* ... details omitted ... */ /* ... details omitted ... */
public static UserAccount readThrough(String userId) { public UserAccount readThrough(final String userId) {
if (cache.contains(userId)) { if (cache.contains(userId)) {
LOGGER.info("# Cache Hit!"); LOGGER.info("# Found in Cache!");
return cache.get(userId); return cache.get(userId);
} }
LOGGER.info("# Cache Miss!"); LOGGER.info("# Not found in cache! Go to DB!!");
UserAccount userAccount = DbManager.readFromDb(userId); UserAccount userAccount = dbManager.readFromDb(userId);
cache.set(userId, userAccount); cache.set(userId, userAccount);
return userAccount; return userAccount;
} }
public static void writeThrough(UserAccount userAccount) { public void writeThrough(final UserAccount userAccount) {
if (cache.contains(userAccount.getUserId())) { if (cache.contains(userAccount.getUserId())) {
DbManager.updateDb(userAccount); dbManager.updateDb(userAccount);
} else { } else {
DbManager.writeToDb(userAccount); dbManager.writeToDb(userAccount);
} }
cache.set(userAccount.getUserId(), userAccount); cache.set(userAccount.getUserId(), userAccount);
} }
public void writeAround(final UserAccount userAccount) {
if (cache.contains(userAccount.getUserId())) {
dbManager.updateDb(userAccount);
// Cache data has been updated -- remove older
cache.invalidate(userAccount.getUserId());
// version from cache.
} else {
dbManager.writeToDb(userAccount);
}
}
public static void clearCache() { public static void clearCache() {
if (cache != null) { if (cache != null) {
cache.clear(); cache.clear();
@ -225,34 +228,39 @@ class.
public final class AppManager { public final class AppManager {
private static CachingPolicy cachingPolicy; private static CachingPolicy cachingPolicy;
private final DbManager dbManager;
private final CacheStore cacheStore;
private AppManager() { private AppManager() {
} }
public static void initDb(boolean useMongoDb) { /* ... */ } public void initDb() { /* ... */ }
public static void initCachingPolicy(CachingPolicy policy) { /* ... */ } public static void initCachingPolicy(CachingPolicy policy) { /* ... */ }
public static void initCacheCapacity(int capacity) { /* ... */ } public static void initCacheCapacity(int capacity) { /* ... */ }
public static UserAccount find(String userId) { public UserAccount find(final String userId) {
if (cachingPolicy == CachingPolicy.THROUGH || cachingPolicy == CachingPolicy.AROUND) { LOGGER.info("Trying to find {} in cache", userId);
return CacheStore.readThrough(userId); if (cachingPolicy == CachingPolicy.THROUGH
|| cachingPolicy == CachingPolicy.AROUND) {
return cacheStore.readThrough(userId);
} else if (cachingPolicy == CachingPolicy.BEHIND) { } else if (cachingPolicy == CachingPolicy.BEHIND) {
return CacheStore.readThroughWithWriteBackPolicy(userId); return cacheStore.readThroughWithWriteBackPolicy(userId);
} else if (cachingPolicy == CachingPolicy.ASIDE) { } else if (cachingPolicy == CachingPolicy.ASIDE) {
return findAside(userId); return findAside(userId);
} }
return null; return null;
} }
public static void save(UserAccount userAccount) { public void save(final UserAccount userAccount) {
LOGGER.info("Save record!");
if (cachingPolicy == CachingPolicy.THROUGH) { if (cachingPolicy == CachingPolicy.THROUGH) {
CacheStore.writeThrough(userAccount); cacheStore.writeThrough(userAccount);
} else if (cachingPolicy == CachingPolicy.AROUND) { } else if (cachingPolicy == CachingPolicy.AROUND) {
CacheStore.writeAround(userAccount); cacheStore.writeAround(userAccount);
} else if (cachingPolicy == CachingPolicy.BEHIND) { } else if (cachingPolicy == CachingPolicy.BEHIND) {
CacheStore.writeBehind(userAccount); cacheStore.writeBehind(userAccount);
} else if (cachingPolicy == CachingPolicy.ASIDE) { } else if (cachingPolicy == CachingPolicy.ASIDE) {
saveAside(userAccount); saveAside(userAccount);
} }
@ -272,24 +280,35 @@ Here is what we do in the main class of the application.
@Slf4j @Slf4j
public class App { public class App {
public static void main(String[] args) { public static void main(final String[] args) {
AppManager.initDb(false); boolean isDbMongo = isDbMongo(args);
AppManager.initCacheCapacity(3); if(isDbMongo){
var app = new App(); LOGGER.info("Using the Mongo database engine to run the application.");
} else {
LOGGER.info("Using the 'in Memory' database to run the application.");
}
App app = new App(isDbMongo);
app.useReadAndWriteThroughStrategy(); app.useReadAndWriteThroughStrategy();
String splitLine = "==============================================";
LOGGER.info(splitLine);
app.useReadThroughAndWriteAroundStrategy(); app.useReadThroughAndWriteAroundStrategy();
LOGGER.info(splitLine);
app.useReadThroughAndWriteBehindStrategy(); app.useReadThroughAndWriteBehindStrategy();
LOGGER.info(splitLine);
app.useCacheAsideStategy(); app.useCacheAsideStategy();
LOGGER.info(splitLine);
} }
public void useReadAndWriteThroughStrategy() { public void useReadAndWriteThroughStrategy() {
LOGGER.info("# CachingPolicy.THROUGH"); LOGGER.info("# CachingPolicy.THROUGH");
AppManager.initCachingPolicy(CachingPolicy.THROUGH); appManager.initCachingPolicy(CachingPolicy.THROUGH);
var userAccount1 = new UserAccount("001", "John", "He is a boy."); var userAccount1 = new UserAccount("001", "John", "He is a boy.");
AppManager.save(userAccount1);
LOGGER.info(AppManager.printCacheContent()); appManager.save(userAccount1);
AppManager.find("001"); LOGGER.info(appManager.printCacheContent());
AppManager.find("001"); appManager.find("001");
appManager.find("001");
} }
public void useReadThroughAndWriteAroundStrategy() { /* ... */ } public void useReadThroughAndWriteAroundStrategy() { /* ... */ }
@ -300,16 +319,6 @@ public class App {
} }
``` ```
Finally, here is some of the console output from the program.
```
12:32:53.845 [main] INFO com.iluwatar.caching.App - # CachingPolicy.THROUGH
12:32:53.900 [main] INFO com.iluwatar.caching.App -
--CACHE CONTENT--
UserAccount(userId=001, userName=John, additionalInfo=He is a boy.)
----
```
## Class diagram ## Class diagram
![alt text](./etc/caching.png "Caching") ![alt text](./etc/caching.png "Caching")

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

View File

@ -44,10 +44,19 @@ import lombok.extern.slf4j.Slf4j;
* </p> * </p>
* *
* <p> * <p>
* To run the application with MongoDb: * There are 2 ways to launch the application.
* 1. Launch mongoDB in docker container with command: docker-compose up * - to use "in Memory" database.
* 2. Start application with parameter --mongo * - to use the MongoDb as a database
* Example: java -jar app.jar --mongo *
* To run the application with "in Memory" database, just launch it without parameters
* Example: 'java -jar app.jar'
*
* To run the application with MongoDb you need to be installed the MongoDb
* in your system, or to launch it in the docker container.
* You may launch docker container from the root of current module with command:
* 'docker-compose up'
* Then you can start the application with parameter --mongo
* Example: 'java -jar app.jar --mongo'
* </p> * </p>
* *
* @see CacheStore * @see CacheStore
@ -86,7 +95,13 @@ public class App {
// and the App class to avoid Maven compilation errors. Set flag to // and the App class to avoid Maven compilation errors. Set flag to
// true to run the tests with MongoDB (provided that MongoDB is // true to run the tests with MongoDB (provided that MongoDB is
// installed and socket connection is open). // installed and socket connection is open).
App app = new App(isDbMongo(args)); boolean isDbMongo = isDbMongo(args);
if (isDbMongo) {
LOGGER.info("Using the Mongo database engine to run the application.");
} else {
LOGGER.info("Using the 'in Memory' database to run the application.");
}
App app = new App(isDbMongo);
app.useReadAndWriteThroughStrategy(); app.useReadAndWriteThroughStrategy();
String splitLine = "=============================================="; String splitLine = "==============================================";
LOGGER.info(splitLine); LOGGER.info(splitLine);

View File

@ -36,7 +36,7 @@ import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
public class CacheStore { public class CacheStore {
/** /**
* Cach capacity. * Cache capacity.
*/ */
private static final int CAPACITY = 3; private static final int CAPACITY = 3;

View File

@ -177,7 +177,7 @@ public class LruCache {
} }
/** /**
* Che if Cache cintains the userId. * Check if Cache contains the userId.
* *
* @param userId {@link String} * @param userId {@link String}
* @return boolean * @return boolean