{"id":20606010,"url":"https://github.com/totbwf/fsharp.data.dataloader","last_synced_at":"2025-07-26T18:17:37.278Z","repository":{"id":49743673,"uuid":"95258161","full_name":"TOTBWF/FSharp.Data.Dataloader","owner":"TOTBWF","description":"A F# Library for simplifying access to remote data, with caching and batching","archived":false,"fork":false,"pushed_at":"2017-10-18T22:42:51.000Z","size":26,"stargazers_count":12,"open_issues_count":0,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-03-28T14:21:46.209Z","etag":null,"topics":["batching","caching","dataloader","fsharp"],"latest_commit_sha":null,"homepage":null,"language":"F#","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/TOTBWF.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-06-23T21:35:22.000Z","updated_at":"2025-02-14T14:22:36.000Z","dependencies_parsed_at":"2022-09-14T13:01:29.684Z","dependency_job_id":null,"html_url":"https://github.com/TOTBWF/FSharp.Data.Dataloader","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TOTBWF%2FFSharp.Data.Dataloader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TOTBWF%2FFSharp.Data.Dataloader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TOTBWF%2FFSharp.Data.Dataloader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/TOTBWF%2FFSharp.Data.Dataloader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/TOTBWF","download_url":"https://codeload.github.com/TOTBWF/FSharp.Data.Dataloader/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248994893,"owners_count":21195467,"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":["batching","caching","dataloader","fsharp"],"created_at":"2024-11-16T09:32:05.168Z","updated_at":"2025-04-15T02:35:15.806Z","avatar_url":"https://github.com/TOTBWF.png","language":"F#","readme":"# FSharp.Data.Dataloader\n\n\n### What is Dataloader?\nDataloader is a generic utility meant to be used in your application's data fetch layer to\nprovide batching and caching.\n\nThis is a spiritual port of the [Haxl](https://github.com/facebook/Haxl) library for Haskell.\n\n\n## Getting Started\nFirst, install and build the library.\n\n```sh\ncd src\ndotnet restore\ndotnet build\n```\nFor our example, we are going to show how to make a simple blog using Dataloader.\n\n\nFirst we are going to make an instance of a request:\n```fsharp\ntype BlogRequest\u003c'a\u003e =\n    | FetchPosts of (int list -\u003e 'a)\n    | FetchPostContent of int * (string option -\u003e 'a)\n    interface Request\u003c'a\u003e with\n        member x.Identifier =\n            match x with\n            | FetchPosts -\u003e \"FetchPosts\"\n            | FetchPostContent id -\u003e \"FetchContent id = \" + id.ToString()\n```\n\nA request encapsulates all of the possible requests you could make to a given datasource, as well as the data needed to make those requests.\n\nNext up we are going to create our DataSource\n```fsharp\nlet blogDataSource() = \n    let fetchfn (blocked: BlockedFetch\u003c'a, BlogRequest\u003c'a\u003e\u003e list) = \n        blocked\n        |\u003e List.iter(fun b -\u003e\n            match b.Request with\n            | FetchPosts cont -\u003e \n                let ids = env.PostIds\n                FetchResult.putSuccess (b.Status) (cont ids)\n            | FetchPostContent(id, cont) -\u003e\n                let content = Map.tryFind id env.PostContents\n                FetchResult.putSuccess (b.Status) (cont content))\n        |\u003e SyncFetch\n    DataSource.create \"Blog\" fetchfn \n```\n\nThe most important part of our datasource is the `fetchfn` function, which describes how we are going to resolve a batch of requests that we are currently blocking on. Note that it returns a `PerformFetch`, which is defined as such:\n```fsharp\ntype PerformFetch =\n    | SyncFetch of unit\n    | AsyncFetch of Async\u003cunit []\u003e\n```\nThis allows us to do fully asynchronous requests, but for now we are just going to use the synchronous version.\n\nFinally, let us see it all composed together:\n```fsharp\nlet fetchPostIds = Fetch.dataFetch\u003cint list, BlogRequest\u003c_\u003e\u003e (blogDataSource()) (FetchPosts id)\nlet fetchPostContent postId = Fetch.dataFetch\u003cstring option, BlogRequest\u003c_\u003e\u003e source (FetchPostContent(postId, id))\nlet renderPosts posts postIds = \n    List.zip posts postIds \n    |\u003e List.map(fun (c, id) -\u003e sprintf \"Id: %d\\n Post: %s\" c id) |\u003e List.fold(fun acc e -\u003e e + \"\\n\" + acc) \"\"\nlet posts = \n    fetchPostIds\n    |\u003e Fetch.bind(Fetch.mapSeq fetchPostContent)\n    |\u003e Fetch.map(Seq.map(Option.defaultWith(fun () -\u003e \"\")) \u003e\u003e Seq.toList)\nlet contents =\n    fetchPostIds\n    |\u003e Fetch.map(renderPosts)\n    |\u003e Fetch.applyTo posts\nlet res =  Fetch.runFetch contents\n ```\n\nCool! Even though we call `fetchPostIds` twice, it will only make that fetch once! This example doesnt gain that much from request batching, but if we decided to implement it (say, if we had a SQL datasource), we would implement it within the `FetchFn` of our DataSource.","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotbwf%2Ffsharp.data.dataloader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ftotbwf%2Ffsharp.data.dataloader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ftotbwf%2Ffsharp.data.dataloader/lists"}