-
Notifications
You must be signed in to change notification settings - Fork 120
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
Add cats-effect to the core module, remove modes #345
Merged
Merged
Changes from 17 commits
Commits
Show all changes
21 commits
Select commit
Hold shift + click to select a range
ac21331
Add cats-effect to the core module, remove modes
kubukoz 30dafe5
Port caffeine module
kubukoz 4505187
It's better if it's traverse! (no, really)
kubukoz b88d5cb
Remove ohc again
kubukoz 3d5438b
Restore line
kubukoz 19495b4
Update cats-effect to 2.1.2
kubukoz 51f84e3
Add Sync requirement to abstract cache, compile core tests
kubukoz 1894d65
F.unit
kubukoz 4259a02
Remove Scalaz module (there are CE instances for Task)
kubukoz 290e453
Bump cats-effect
kubukoz dc92b55
Hopefully compile all tests
kubukoz 3365f90
Fix integration tests
kubukoz 45699fa
Fix more caches
kubukoz 81fa509
Remove cats-effect module
kubukoz 4f2d350
Fix benchmarks and JS compilation
kubukoz 997ed1a
2.11 isn't supported by cats anymore
kubukoz 8691199
Remove 2.11-specific config
kubukoz d772729
remove extra in RedisClusterCache#doPut
lewisjkl 4656021
update docs to get them compiling
lewisjkl 3a991ba
fix mdoc cleanup to close caches by running cache.close
lewisjkl d1c29ad
Remove a couple of TODOs
cb372 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,7 +1,6 @@ | ||
sudo: false | ||
language: scala | ||
scala: | ||
- 2.11.12 | ||
- 2.13.1 | ||
- 2.12.10 | ||
jdk: | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
74 changes: 39 additions & 35 deletions
74
modules/caffeine/src/main/scala/scalacache/caffeine/CaffeineCache.scala
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,79 +1,83 @@ | ||
package scalacache.caffeine | ||
|
||
import java.time.temporal.ChronoUnit | ||
import java.time.{Clock, Instant} | ||
import java.time.{Instant} | ||
|
||
import com.github.benmanes.caffeine.cache.{Caffeine, Cache => CCache} | ||
|
||
import cats.effect.Clock | ||
import scalacache.logging.Logger | ||
import scalacache.{AbstractCache, CacheConfig, Entry, Mode} | ||
import scalacache.{AbstractCache, CacheConfig, Entry} | ||
import scala.concurrent.duration.Duration | ||
import scala.language.higherKinds | ||
import cats.effect.Sync | ||
import java.util.concurrent.TimeUnit | ||
import cats.implicits._ | ||
import cats.MonadError | ||
|
||
/* | ||
* Thin wrapper around Caffeine. | ||
* | ||
* This cache implementation is synchronous. | ||
*/ | ||
class CaffeineCache[V](val underlying: CCache[String, Entry[V]])( | ||
class CaffeineCache[F[_]: Sync, V](val underlying: CCache[String, Entry[V]])( | ||
implicit val config: CacheConfig, | ||
clock: Clock = Clock.systemUTC() | ||
) extends AbstractCache[V] { | ||
clock: Clock[F] | ||
) extends AbstractCache[F, V] { | ||
protected val F: Sync[F] = Sync[F] | ||
|
||
override protected final val logger = Logger.getLogger(getClass.getName) | ||
|
||
def doGet[F[_]](key: String)(implicit mode: Mode[F]): F[Option[V]] = { | ||
mode.M.delay { | ||
val entry = underlying.getIfPresent(key) | ||
val result = { | ||
if (entry == null || entry.isExpired) | ||
None | ||
else | ||
Some(entry.value) | ||
def doGet(key: String): F[Option[V]] = { | ||
F.delay { | ||
Option(underlying.getIfPresent(key)) | ||
} | ||
.flatMap(_.filterA(Entry.isExpired[F, V])) | ||
.map(_.map(_.value)) | ||
.flatTap { result => | ||
logCacheHitOrMiss(key, result) | ||
} | ||
logCacheHitOrMiss(key, result) | ||
result | ||
} | ||
} | ||
|
||
def doPut[F[_]](key: String, value: V, ttl: Option[Duration])(implicit mode: Mode[F]): F[Any] = { | ||
mode.M.delay { | ||
val entry = Entry(value, ttl.map(toExpiryTime)) | ||
underlying.put(key, entry) | ||
logCachePut(key, ttl) | ||
def doPut(key: String, value: V, ttl: Option[Duration]): F[Unit] = | ||
ttl.traverse(toExpiryTime).flatMap { expiry => | ||
F.delay { | ||
val entry = Entry(value, expiry) | ||
underlying.put(key, entry) | ||
} *> logCachePut(key, ttl) | ||
} | ||
} | ||
|
||
override def doRemove[F[_]](key: String)(implicit mode: Mode[F]): F[Any] = | ||
mode.M.delay(underlying.invalidate(key)) | ||
override def doRemove(key: String): F[Unit] = | ||
F.delay(underlying.invalidate(key)) | ||
|
||
override def doRemoveAll[F[_]]()(implicit mode: Mode[F]): F[Any] = | ||
mode.M.delay(underlying.invalidateAll()) | ||
override def doRemoveAll(): F[Unit] = | ||
F.delay(underlying.invalidateAll()) | ||
|
||
override def close[F[_]]()(implicit mode: Mode[F]): F[Any] = { | ||
override def close: F[Unit] = { | ||
// Nothing to do | ||
mode.M.pure(()) | ||
F.unit | ||
} | ||
|
||
private def toExpiryTime(ttl: Duration): Instant = | ||
Instant.now(clock).plus(ttl.toMillis, ChronoUnit.MILLIS) | ||
private def toExpiryTime(ttl: Duration): F[Instant] = | ||
clock.monotonic(TimeUnit.MILLISECONDS).map(Instant.ofEpochMilli(_).plusMillis(ttl.toMillis)) | ||
|
||
} | ||
|
||
object CaffeineCache { | ||
|
||
/** | ||
* Create a new Caffeine cache | ||
* Create a new Caffeine cache. | ||
*/ | ||
def apply[V](implicit config: CacheConfig): CaffeineCache[V] = | ||
apply(Caffeine.newBuilder().build[String, Entry[V]]()) | ||
def apply[F[_]: Sync: Clock, V](implicit config: CacheConfig): F[CaffeineCache[F, V]] = | ||
Sync[F].delay(Caffeine.newBuilder().build[String, Entry[V]]()).map(apply(_)) | ||
|
||
/** | ||
* Create a new cache utilizing the given underlying Caffeine cache. | ||
* | ||
* @param underlying a Caffeine cache | ||
*/ | ||
def apply[V](underlying: CCache[String, Entry[V]])(implicit config: CacheConfig): CaffeineCache[V] = | ||
def apply[F[_]: Sync: Clock, V]( | ||
underlying: CCache[String, Entry[V]] | ||
)(implicit config: CacheConfig): CaffeineCache[F, V] = | ||
new CaffeineCache(underlying) | ||
|
||
} |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
nit: let's write one-liners like this as
F.delay(...)
instead of with curly braces.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I have a personal preference of putting by-name parameters in curly braces (if the parameter list only has one parameter), especially when lifting side effects. But I can adjust :)