{"id":32305844,"url":"https://github.com/guojiex/expire_cache","last_synced_at":"2025-10-23T06:56:49.582Z","repository":{"id":56828589,"uuid":"166475466","full_name":"guojiex/expire_cache","owner":"guojiex","description":"A dart FIFO auto expire cache. Should be used in flutter search.","archived":false,"fork":false,"pushed_at":"2021-07-11T03:52:18.000Z","size":42,"stargazers_count":15,"open_issues_count":1,"forks_count":2,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-10-23T06:56:18.537Z","etag":null,"topics":["cache","dart","fifo-cache","flutter","mutex","searchdelegate"],"latest_commit_sha":null,"homepage":"https://pub.dev/packages/expire_cache","language":"Dart","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/guojiex.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","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":"2019-01-18T21:35:11.000Z","updated_at":"2022-04-24T21:42:56.000Z","dependencies_parsed_at":"2022-08-26T14:10:44.448Z","dependency_job_id":null,"html_url":"https://github.com/guojiex/expire_cache","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/guojiex/expire_cache","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guojiex%2Fexpire_cache","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guojiex%2Fexpire_cache/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guojiex%2Fexpire_cache/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guojiex%2Fexpire_cache/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/guojiex","download_url":"https://codeload.github.com/guojiex/expire_cache/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/guojiex%2Fexpire_cache/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":280577133,"owners_count":26354073,"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","status":"online","status_checked_at":"2025-10-23T02:00:06.710Z","response_time":142,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["cache","dart","fifo-cache","flutter","mutex","searchdelegate"],"created_at":"2025-10-23T06:56:48.626Z","updated_at":"2025-10-23T06:56:49.567Z","avatar_url":"https://github.com/guojiex.png","language":"Dart","funding_links":[],"categories":[],"sub_categories":[],"readme":"# expire_cache\n\n![build status](https://travis-ci.com/guojiex/expire_cache.svg?branch=master)\n\nA dart package provides FIFO cache and its entries will expire according to time. Also proviodes\nmutex like method for search usage. Check out example/async_search_example.dart.\n\n\nIf you want to implement \n[SearchDelegate](https://github.com/flutter/flutter/search?q=SearchDelegate\u0026unscoped_q=SearchDelegate) \nin your app, you will have to cache your search results. Otherwise your call to search backend might run multiple times for the same query.\n\nSee:\n\nhttps://github.com/flutter/flutter/issues/11655#issuecomment-412413030\n\nhttps://github.com/flutter/flutter/issues/26759\n\nBecause this is related to search, it is valuable to expire the cache after a period of time, to give user fresh search result.\nAnd this package provide markAsInflight function, to make sure all the later get function gets the same result(if the key is the same).\n\n## Getting Started\n\nThis project is a starting point for a Dart\n[package](https://flutter.io/developing-packages/),\na library module containing code that can be shared easily across\nmultiple Flutter or Dart projects.\n\nFor help getting started with Flutter, view our \n[online documentation](https://flutter.io/docs), which offers tutorials, \nsamples, guidance on mobile development, and a full API reference.\n\n## Development\n\n### Run test\n\n```bash\npub run test test/\n```\n\nor\n\n```bash\ndart pub test test/\n```\n\n## Examples\n\nfind our test file to see how to use.\n\n### Search Example\n\n```\nclass CustomSearchDataSource {\n// FIFO TTL cache to cache search result.\nfinal ExpireCache\u003cSearchQuery, SearchResults\u003e _cache =\n      ExpireCache\u003cSearchQuery, SearchResults\u003e();\n\n  Future\u003cSearchResults\u003e cachedSearch(final SearchQuery searchQuery) async {\n    if (!_cache.isKeyInFlightOrInCache(searchQuery)) {\n      _cache.markAsInFlight(searchQuery);\n    } else {\n      return await _cache.get(searchQuery);\n    }\n    // searchQuery.runSearch is the real search call to backend\n    final result = await searchQuery.runSearch(this.api);\n    _cache.set(searchQuery, result);\n    print('call search backend');\n    return result;\n  }\n\n}\n```\n\n### Normal Cache Function\n\n```dart\nfinal sizeLimit = 3;\nfinal expireDuration = Duration(seconds: 120);\nExpireCache\u003cint, int\u003e cache = ExpireCache\u003cint, int\u003e(expireDuration: expireDuration, sizeLimit: 3);\nfor (int i = 0; i \u003c sizeLimit; i++) {\n    cache.set(i, i);\nprint(cache.get(0)); // 0\n```\n\n### Mutex like usage in Search\n\n```dart\nimport 'package:expire_cache/expire_cache.dart';\n\nclass _SearchObjectWithMutex {\n  static int cacheSetCount = 0;\n  static void getInflightOrSet(\n      ExpireCache\u003cString, String\u003e cache, String key, String value) async {\n    if (!cache.isKeyInFlightOrInCache(key)) {\n      cache.markAsInFlight(key);\n    } else {\n      await cache.get(key);\n      return;\n    }\n    cacheSetCount++;\n    await cache.set(key, value);\n  }\n}\n\nclass _SearchObjectWithoutMutex {\n  static int cacheSetCount = 0;\n  static void getOrSet(\n      ExpireCache\u003cString, String\u003e cache, String key, String value) async {\n    if (await cache.get(key) != null) {\n      return;\n    }\n    cacheSetCount++;\n    await cache.set(key, value);\n  }\n}\n\nvoid main() async {\n  ExpireCache\u003cString, String\u003e cache = ExpireCache\u003cString, String\u003e();\n  _SearchObjectWithMutex.getInflightOrSet(cache, 'key', 'value');\n  await _SearchObjectWithMutex.getInflightOrSet(cache, 'key', 'value');\n  // Cache should only be set once.\n  print(\n      'with mutex ${_SearchObjectWithMutex.cacheSetCount}'); // 1, set is called only once.\n\n  cache.clear();\n  _SearchObjectWithoutMutex.getOrSet(cache, 'key', 'value2');\n  await _SearchObjectWithoutMutex.getOrSet(cache, 'key', 'value2');\n  // Cache should only be set once.\n  print(\n      'without mutex ${_SearchObjectWithoutMutex.cacheSetCount}'); // 2, because the get/set pair are run at the same time, both get will get null.\n}\n\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguojiex%2Fexpire_cache","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fguojiex%2Fexpire_cache","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fguojiex%2Fexpire_cache/lists"}