diff --git a/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJar.scala b/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJar.scala index aefc87a..5a6be4e 100644 --- a/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJar.scala +++ b/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJar.scala @@ -12,18 +12,25 @@ private[snickerdoodle] object SnCookieJar { private[snickerdoodle] class Http4sPersistenceCookieJarImpl[F[_]: Concurrent: Clock]( persistence: SnCookiePersistence[F], supervisor: Supervisor[F], + synchronousPersistence: Boolean, ref: Ref[F, Map[SnCookie.SnCookieKey, SnCookie]], isPublicSuffix: String => Boolean ) extends CookieJar[F]{ + + def persist[A](fa: F[A]): F[Unit] = { + if (synchronousPersistence) fa.void + else supervisor.supervise(fa).void + } + def evictExpired: F[Unit] = for { now <- HttpDate.current[F].map(_.epochSecond) _ <- ref.update(_.filter(t => now <= t._2.expiry)) - _ <- supervisor.supervise(persistence.clearExpired(now)) + _ <- persist(persistence.clearExpired(now)) } yield () def evictAll: F[Unit] = - ref.set(Map.empty) >> - persistence.clear + ref.set(Map.empty) >> + persist(persistence.clear) def addCookies[G[_]: Foldable](cookies: G[(ResponseCookie, Uri)]): F[Unit] = for { @@ -36,7 +43,7 @@ private[snickerdoodle] object SnCookieJar { snO.fold(m)(v => m + v) } _ <- ref.update(m => m ++ map) - _ <- supervisor.supervise(map.toList.traverse_{ case (_, c) => if (c.persist) persistence.create(c) else Applicative[F].unit}).void + _ <- persist(map.toList.traverse_{ case (_, c) => if (c.persist) persistence.create(c) else Applicative[F].unit}).void } yield () def enrichRequest[G[_]](r: Request[G]): F[Request[G]] = for { @@ -51,7 +58,7 @@ private[snickerdoodle] object SnCookieJar { } (m ++ updatedMap, filtered) } - _ <- supervisor.supervise(cookies.traverse_(c => if (c.persist) persistence.updateLastAccessed(SnCookie.SnCookieKey.fromCookie(c), c.lastAccessed) else Applicative[F].unit)) + _ <- persist(cookies.traverse_(c => if (c.persist) persistence.updateLastAccessed(SnCookie.SnCookieKey.fromCookie(c), c.lastAccessed) else Applicative[F].unit)) } yield cookies.foldLeft(r){ case (r, c) => r.addCookie(SnCookie.toRequestCookie(c))} } diff --git a/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJarBuilder.scala b/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJarBuilder.scala index 2d37439..2ef9196 100644 --- a/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJarBuilder.scala +++ b/core/shared/src/main/scala/io/chrisdavenport/snickerdoodle/SnCookieJarBuilder.scala @@ -10,12 +10,14 @@ final class SnCookieJarBuilder[F[_]: Async] private ( private val supervisorO: Option[Supervisor[F]], private val persistenceO: Option[Resource[F, SnCookiePersistence[F]]], private val isPublicSuffixO: Option[Resource[F, String => Boolean]], -){ self => + private val synchronousPersistence: Boolean, +){ self => def copy( supervisorO: Option[Supervisor[F]] = self.supervisorO, persistenceO: Option[Resource[F, SnCookiePersistence[F]]] = self.persistenceO, - isPublicSuffixO: Option[Resource[F, String => Boolean]] = self.isPublicSuffixO - ): SnCookieJarBuilder[F] = new SnCookieJarBuilder[F](supervisorO, persistenceO, isPublicSuffixO) + isPublicSuffixO: Option[Resource[F, String => Boolean]] = self.isPublicSuffixO, + synchronousPersistence: Boolean = self.synchronousPersistence + ): SnCookieJarBuilder[F] = new SnCookieJarBuilder[F](supervisorO, persistenceO, isPublicSuffixO, synchronousPersistence) def withSupervisor(s: Supervisor[F]) = copy(supervisorO = s.some) @@ -24,6 +26,9 @@ final class SnCookieJarBuilder[F[_]: Async] private ( def withPersistence(c: SnCookiePersistence[F]) = copy(persistenceO = c.pure[Resource[F, *]].some) + def withSynchronousPersistence = copy(synchronousPersistence = true) + def withAsynchronousPersistence = copy(synchronousPersistence = false) + def withoutPersistence = copy(persistenceO = None) def withIsPublicSuffix(f: String => Boolean) = copy(isPublicSuffixO = f.pure[Resource[F, *]].some) @@ -44,7 +49,7 @@ final class SnCookieJarBuilder[F[_]: Async] private ( ) ) isPublicSuffix <- isPublicSuffixO.getOrElse({(_: String) => false}.pure[Resource[F, *]]) - out = tO.fold[CookieJar[F]](new SnCookieJar.Http4sMemoryCookieJarImpl[F](state, isPublicSuffix)){ case (cp, s) => new SnCookieJar.Http4sPersistenceCookieJarImpl[F](cp, s, state, isPublicSuffix)} + out = tO.fold[CookieJar[F]](new SnCookieJar.Http4sMemoryCookieJarImpl[F](state, isPublicSuffix)){ case (cp, s) => new SnCookieJar.Http4sPersistenceCookieJarImpl[F](cp, s, synchronousPersistence, state, isPublicSuffix)} _ <- Resource.eval(out.evictExpired) } yield out @@ -66,16 +71,17 @@ final class SnCookieJarBuilder[F[_]: Async] private ( ) ) isPublicSuffix <- isPublicSuffixO.getOrElse({(_: String) => false}.pure[Resource[F, *]]) - cj = tO.fold[CookieJar[F]](new SnCookieJar.Http4sMemoryCookieJarImpl[F](state, isPublicSuffix)){ case (cp, s) => new SnCookieJar.Http4sPersistenceCookieJarImpl[F](cp, s, state, isPublicSuffix)} + cj = tO.fold[CookieJar[F]](new SnCookieJar.Http4sMemoryCookieJarImpl[F](state, isPublicSuffix)){ case (cp, s) => new SnCookieJar.Http4sPersistenceCookieJarImpl[F](cp, s, synchronousPersistence, state, isPublicSuffix)} _ <- Resource.eval(cj.evictExpired) } yield (cj, state) } } object SnCookieJarBuilder { - def default[F[_]: Async]: SnCookieJarBuilder[F] = new SnCookieJarBuilder[F](None, None, Defaults.isPublicSuffix) + def default[F[_]: Async]: SnCookieJarBuilder[F] = new SnCookieJarBuilder[F](None, None, Defaults.isPublicSuffix, Defaults.synchronousPersistence) private object Defaults extends SnCookieJarBuilderDefaultsPlaftom { + val synchronousPersistence = true } } \ No newline at end of file