{"id":19254850,"url":"https://github.com/sciss/filecache","last_synced_at":"2025-06-19T09:34:39.110Z","repository":{"id":7789642,"uuid":"9159628","full_name":"Sciss/FileCache","owner":"Sciss","description":"A simple file cache management. Mirror of https://codeberg.org/sciss/FileCache","archived":false,"fork":false,"pushed_at":"2021-07-22T12:30:40.000Z","size":155,"stargazers_count":0,"open_issues_count":3,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-02-23T17:22:54.863Z","etag":null,"topics":["caching","filecache"],"latest_commit_sha":null,"homepage":"","language":"Scala","has_issues":false,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"lgpl-2.1","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/Sciss.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-04-02T01:10:25.000Z","updated_at":"2023-08-15T19:26:00.000Z","dependencies_parsed_at":"2022-09-07T18:00:30.499Z","dependency_job_id":null,"html_url":"https://github.com/Sciss/FileCache","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/Sciss/FileCache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sciss%2FFileCache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sciss%2FFileCache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sciss%2FFileCache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sciss%2FFileCache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Sciss","download_url":"https://codeload.github.com/Sciss/FileCache/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Sciss%2FFileCache/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":260724829,"owners_count":23052820,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["caching","filecache"],"created_at":"2024-11-09T18:36:54.028Z","updated_at":"2025-06-19T09:34:34.084Z","avatar_url":"https://github.com/Sciss.png","language":"Scala","funding_links":[],"categories":[],"sub_categories":[],"readme":"# FileCache\n\n[![Build Status](https://github.com/Sciss/FileCache/workflows/Scala%20CI/badge.svg?branch=main)](https://github.com/Sciss/FileCache/actions?query=workflow%3A%22Scala+CI%22)\n[![Maven Central](https://maven-badges.herokuapp.com/maven-central/de.sciss/filecache-common_2.13/badge.svg)](https://maven-badges.herokuapp.com/maven-central/de.sciss/filecache-common_2.13)\n\n## statement\n\nFileCache is a simple building block for the Scala programming language, managing a directory with cache files.\nIt is (C)opyright 2013\u0026ndash;2020 by Hanns Holger Rutz. All rights reserved. This project is released under \nthe [GNU Lesser General Public License](https://raw.github.com/Sciss/FileCache/main/LICENSE) v2.1+ and comes with \nabsolutely no warranties. To contact the author, send an e-mail to `contact at sciss.de`.\n\n## linking\n\nTo link to this library, use either of the following artifacts:\n\n    \"de.sciss\" %% \"filecache-mutable\" % v\n    \"de.sciss\" %% \"filecache-txn\"     % v\n\nThe current version `v` is `\"1.1.2\"`. The `-mutable` variant provides a (thread-safe) mutable cache object, \nwhereas the `-txn` variant uses the [scala-stm](https://github.com/nbronson/scala-stm) software transactional memory.\n\n## building\n\nThis project builds with sbt against Scala 2.13, 2.12, 3. \nThe last version to support Scala 2.11 was v0.5.1.\n\nThe project is documented through scaladoc run `sbt doc` to create the API docs.\n\n## documentation\n\nHere is an example of the mutable package, the transactional package works analogously. A cache is represented by \nthe `MutableProducer[Key, Value]` type. Therefore, a resource (the value) is identified by and can be looked up with \na key. A producer is created by calling `apply` on the companion object, requiring implicit values for key and value \nserializers (`de.sciss.serial.ConstFormat`). Serializers are readily available for primitive types and some \ncombinators (e.g. `Tuple2` or `IndexedSeq`).\n\nFor example, let us assume the key type is `String`, and the value type is `IndexedSeq[Int]`. First of all, we need \nto create a configuration for the cache. A mutable `ConfigBuilder` is obtained by calling `Config[Key, Value]()`. It \nwill be implicitly frozen as a `Config` object when the builder is passed into the producer constructor. We'll go \nwith the defaults except changing the cache capacity to hold at maximum two entries (the default is unlimited), and \nwe'll assign an eviction function that prints to the console when a cache entry is removed from disk.\n\n```scala\n\n    import de.sciss.filecache._\n\n    type Vec[+A] = collection.immutable.IndexedSeq[A]\n    val c = Config[String, Vec[Int]]()\n    c.capacity = Limit(count = 2)\n    c.evict = { (key, value) =\u003e println(s\"Evicted key $key\") }\n    val p = MutableProducer(c)\n```\n\nThe producer is like an exclusive handle to resources. A resource can be obtained with method\n\n```scala\n\n    def acquire(key: A)(source: =\u003e B): Future[B]\n````\n\nWhere the `source` thunk is executed only if the resource for `key` was not found in the cache. When the resource \nis not used any longer, it must be released using\n\n```scala\n\n    def release(key: A): Unit\n```\n\nIf your application wants to be able to have multiple handles on a resource, a second structure `MutableConsumer` \ncan be used which simply wraps a producer with an internal use count. Here the acquirement is a more simple method \n`def acquire(key: A): Future[B]` which may be called multiple times. Each acquirement should be matched with an \neventual `release` call.\n\nFor our example, we will just use the exclusive producer. Cache production happens inside a `Future`, so if we want \nto see the result, we can use the future's `foreach` method. A suitable `ExecutionContext` can be found by importing \n`p.executionContext` (that context was defined in the original configuration).\n\n```scala\n\n    import p.executionContext\n    import scala.concurrent._\n    import duration.Duration\n\n    val foo1 = p.acquire(\"foo\") { println(\"Producing...\"); Vector(1, 2, 3) }\n    Await.result(foo1, Duration.Inf)  // Vector(1, 2, 3)\n```\n\nLet's release and re-acquire that resource. It should be cached:\n\n```scala\n\n    p.release(\"foo\")\n    val foo2 = p.acquire(\"foo\")(???)\n    Await.result(foo2, Duration.Inf)  // Vector(1, 2, 3)\n```\n\nIf we release `\"foo\"` and produce new entries in the cache, we can witness the eviction:\n\n```scala\n\n    p.release(\"foo\")\n    val bar = p.acquire(\"bar\") { Vector(4, 5, 6) }\n    val baz = p.acquire(\"baz\") { Vector(7, 8, 9) }  // causes eviction of \"foo\"\n```\n\nNote that an entry is never evicted while acquired.\n\nSome more notes:\n\n- the capacity `Limit` has two conditions, a `count` for the maximum number of entries and a `space` for the maximum \ntotal size in bytes. A value of `-1` for each of these (default) means no limit. Both limits work together, so if \nboth `count` and `space` are specified, the capacity will be constrained to satisfy these two properties.\n- if using a `space` limit, the `space` _function_ in the configuration must be provided. This function is given a \n  key-value pair and must return the resource size in bytes. The reason this is not automatically equated with the \n  size of the serialized value is that often a resource extends beyond the directly given value. For example, if the \n  cache is used to produce waveform overviews for a sound file, the value might just point to the waveform file. But \n  the size of the resource is then determined by the size of that waveform file, not the cache entry which is just \n  the path name to that file.\n- a producer can be disposed calling the `dispose` method. This will release all currently acquired keys.\n- the cache directory is specified in the configuration using the `folder` variable. A second variable `extension` \n  can be used to specify the file extension.\n- the current cache size is available through the `usage` method on a producer\n- cache values may become invalid for some reason. As an example, imagine again the sound file waveform cache. If \n  the sound file whose waveform is produced has changed, then obviously the waveform overview must be re-computed. \n  If that case may occur in your scenario, the function `accept` in the configuration should be specified. It is \n  given a key-value pair and must return a boolean. A return value `true` indicates that the cache entry is still \n  valid, a value of `false` will cause the re-run of the producer function and overwrite the cache entry with the \n  new result. In the sound file example, we may store the last-modified time-stamp of the sound file in the cache \n  value, so we can quickly determine whether the file has changed. In this scenario it is also important to use the \n  configuration's `evict` function to delete the additional resources (the waveform file).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsciss%2Ffilecache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsciss%2Ffilecache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsciss%2Ffilecache/lists"}