-
Notifications
You must be signed in to change notification settings - Fork 7
[EB-168] remove the usages of Guava library #169
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 4 commits
07e7202
3b55fc9
839923f
06863d7
0977b6d
25dddd0
699a405
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,18 @@ | ||
| package com.exadel.etoolbox.backpack.core.services.pckg; | ||
|
|
||
| import com.exadel.etoolbox.backpack.core.dto.response.PackageInfo; | ||
|
|
||
| /** | ||
| * Narrow cache-facing API for storing and retrieving package build information. | ||
| */ | ||
| public interface PackageInfoCache { | ||
|
|
||
| PackageInfo get(String packagePath); | ||
|
|
||
| PackageInfo put(String packagePath, PackageInfo packageInfo); | ||
|
|
||
| PackageInfo remove(String packagePath); | ||
|
|
||
| void clear(); | ||
| } | ||
|
|
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,112 @@ | ||
| package com.exadel.etoolbox.backpack.core.services.pckg.impl; | ||
|
|
||
| import com.exadel.etoolbox.backpack.core.dto.response.PackageInfo; | ||
| import com.exadel.etoolbox.backpack.core.services.pckg.PackageInfoCache; | ||
|
|
||
| import java.util.Iterator; | ||
| import java.util.Map; | ||
| import java.util.Objects; | ||
| import java.util.concurrent.ConcurrentHashMap; | ||
| import java.util.concurrent.ConcurrentMap; | ||
|
|
||
| final class PackageInfoCacheImpl implements PackageInfoCache { | ||
|
|
||
| private static final int MAX_CACHE_SIZE = 100; | ||
|
|
||
| private final ConcurrentMap<String, CacheEntry> packageInfos = new ConcurrentHashMap<>(); | ||
| private final long cacheTtlMillis; | ||
|
|
||
| PackageInfoCacheImpl(long cacheTtlMillis) { | ||
| this.cacheTtlMillis = cacheTtlMillis; | ||
| } | ||
|
|
||
| private static final class CacheEntry { | ||
|
liubou-masiuk marked this conversation as resolved.
Outdated
|
||
| private final PackageInfo value; | ||
| private final long expiresAt; | ||
|
|
||
| private CacheEntry(PackageInfo value, long expiresAt) { | ||
| this.value = value; | ||
| this.expiresAt = expiresAt; | ||
| } | ||
|
|
||
| private boolean isExpired(long now) { | ||
| return expiresAt <= now; | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public PackageInfo get(String key) { | ||
| CacheEntry entry = packageInfos.get(key); | ||
| if (entry == null) { | ||
| return null; | ||
| } | ||
| return unwrapEntry(key, entry); | ||
| } | ||
|
|
||
| @Override | ||
| public PackageInfo put(String key, PackageInfo value) { | ||
| Objects.requireNonNull(value); | ||
|
liubou-masiuk marked this conversation as resolved.
Outdated
|
||
| synchronized (this) { | ||
|
liubou-masiuk marked this conversation as resolved.
Outdated
|
||
| evictExpiredEntries(); | ||
| ensureCapacityFor(key); | ||
| CacheEntry previous = packageInfos.put(key, newCacheEntry(value)); | ||
| return previous == null ? null : unwrapEntry(key, previous); | ||
| } | ||
| } | ||
|
|
||
| @Override | ||
| public PackageInfo remove(String key) { | ||
| CacheEntry removed = packageInfos.remove(key); | ||
| return removed == null ? null : unwrapEntry(key, removed); | ||
| } | ||
|
|
||
| @Override | ||
| public void clear() { | ||
| packageInfos.clear(); | ||
| } | ||
|
|
||
| private CacheEntry newCacheEntry(PackageInfo value) { | ||
| long expiresAt; | ||
| if (cacheTtlMillis < 0) { | ||
| expiresAt = Long.MAX_VALUE; | ||
| } else if (cacheTtlMillis == 0) { | ||
| expiresAt = 0L; | ||
|
liubou-masiuk marked this conversation as resolved.
|
||
| } else { | ||
| expiresAt = System.currentTimeMillis() + cacheTtlMillis; | ||
| } | ||
| return new CacheEntry(value, expiresAt); | ||
| } | ||
|
|
||
| private PackageInfo unwrapEntry(String key, CacheEntry entry) { | ||
| long now = System.currentTimeMillis(); | ||
| if (entry.isExpired(now)) { | ||
| if (key != null) { | ||
| packageInfos.remove(key, entry); | ||
| } | ||
| return null; | ||
| } | ||
| return entry.value; | ||
| } | ||
|
|
||
| private void evictExpiredEntries() { | ||
| long now = System.currentTimeMillis(); | ||
| packageInfos.entrySet() | ||
| .removeIf(entry -> entry.getValue().isExpired(now)); | ||
| } | ||
|
|
||
| private void ensureCapacityFor(String key) { | ||
| if (packageInfos.containsKey(key) || packageInfos.size() < MAX_CACHE_SIZE) { | ||
| return; | ||
| } | ||
| evictOneEntry(); | ||
| } | ||
|
|
||
| private void evictOneEntry() { | ||
| Iterator<Map.Entry<String, CacheEntry>> iterator = packageInfos.entrySet().iterator(); | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can we evict not any entry but the oldest one?
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. We could, but this will introduce some complexity - we don't have something like concurrentLinkedHashMap ootb, so we'll have to track the incertion order manually. We'll have to add more synchronized blocks to basically all main methods. I am just not sure that this is justified, for this case |
||
| if (iterator.hasNext()) { | ||
| iterator.next(); | ||
| iterator.remove(); | ||
| } | ||
|
liubou-masiuk marked this conversation as resolved.
|
||
| } | ||
| } | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.