{"id":16092296,"url":"https://github.com/alecthomas/replaylog","last_synced_at":"2025-04-12T06:11:11.219Z","repository":{"id":57662958,"uuid":"479359160","full_name":"alecthomas/replaylog","owner":"alecthomas","description":"A type safe implementation of an op replay log","archived":false,"fork":false,"pushed_at":"2024-01-01T08:41:44.000Z","size":12,"stargazers_count":3,"open_issues_count":0,"forks_count":1,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-26T01:36:21.897Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Go","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/alecthomas.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":".github/FUNDING.yml","license":"COPYING","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null},"funding":{"github":["alecthomas"]}},"created_at":"2022-04-08T11:13:17.000Z","updated_at":"2022-05-10T11:32:50.000Z","dependencies_parsed_at":"2024-06-20T00:20:01.620Z","dependency_job_id":"aa48a2be-78c3-403a-aea3-678fbe958b5f","html_url":"https://github.com/alecthomas/replaylog","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Freplaylog","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Freplaylog/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Freplaylog/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/alecthomas%2Freplaylog/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/alecthomas","download_url":"https://codeload.github.com/alecthomas/replaylog/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248525138,"owners_count":21118619,"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":[],"created_at":"2024-10-09T16:06:50.772Z","updated_at":"2025-04-12T06:11:11.201Z","avatar_url":"https://github.com/alecthomas.png","language":"Go","funding_links":["https://github.com/sponsors/alecthomas"],"categories":[],"sub_categories":[],"readme":"# A type safe implementation of a replay log for Go\n\n[![PkgGoDev](https://pkg.go.dev/badge/github.com/alecthomas/replaylog)](https://pkg.go.dev/github.com/alecthomas/replaylog) [![GHA Build](https://github.com/alecthomas/replaylog/actions/workflows/ci.yml/badge.svg)](https://github.com/alecthomas/replaylog/actions)\n[![Go Report Card](https://goreportcard.com/badge/github.com/alecthomas/replaylog)](https://goreportcard.com/report/github.com/alecthomas/replaylog) [![Slack chat](https://img.shields.io/static/v1?logo=slack\u0026style=flat\u0026label=slack\u0026color=green\u0026message=gophers)](https://gophers.slack.com/messages/CN9DS8YF3)\n\nA [replay log](https://ahmet.im/blog/the-replay-pattern/)\n([related](https://engineering.linkedin.com/distributed-systems/log-what-every-software-engineer-should-know-about-real-time-datas-unifying))\nrecords the sequence of operations for mutating an empty\nstate to its final state. The previous final state can then be reconstructed\nfrom the log by starting with an empty state, reading each operation\nfrom the log, and applying it to the state until the final state is reached.\n\n\nThe Log is not safe for concurrent use across processes.\n\n## Example\n\nA simple key-value store:\n\n```go\ntype KV map[string]string\n\ntype Set struct {\n    Key   string `json:\"k\"`\n    Value string `json:\"v\"`\n}\n\nfunc (s *Set) Apply(kv KV) error {\n    kv[s.Key] = s.Value\n    return nil\n}\n\ntype Delete struct {\n    Key string `json:\"k\"`\n}\n\nfunc (d *Delete) Apply(state KV) error {\n    delete(state, d.Key)\n    return nil\n}\n\nfunc main() {\n    ops := []Op[KV]{\u0026Set{}, \u0026Delete{}}\n\n    w, err := ioutil.TempFile(\"\", \"\")\n\n    log, err := New[KV](w, ops...)\n\n    err = log.Append(\u0026Set{Key: \"foo\", Value: \"bar\"})\n    err = log.Append(\u0026Set{Key: \"bar\", Value: \"waz\"})\n    err = log.Append(\u0026Delete{Key: \"foo\"})\n\n    state := KV{}\n\t\n    err = log.Rewind()\n    err = log.Replay(state)\n\n    fmt.Printf(\"%#v\\n\", state)\n}\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecthomas%2Freplaylog","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Falecthomas%2Freplaylog","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Falecthomas%2Freplaylog/lists"}