Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Git infrastructure with Go
Search
Sponsored
·
Your Podcast. Everywhere. Effortlessly.
Share. Educate. Inspire. Entertain. You do you. We'll handle the rest.
→
David Calavera
February 21, 2015
Programming
600
3
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
Git infrastructure with Go
Talk for Gophercon India 2015 about using Go to manage large git data system.
David Calavera
February 21, 2015
More Decks by David Calavera
See All by David Calavera
The language of Chatops
calavera
0
160
How GitHub develops, ships and supports GitHub Enterprise
calavera
2
470
Project Warbird
calavera
1
170
Trinidad
calavera
0
48
JRuby hacking guide
calavera
0
80
My name is Trinidad
calavera
0
78
Other Decks in Programming
See All in Programming
フロントエンドとバックエンドで「1文字」を揃えよう
youkidearitai
PRO
0
240
LLM Plugin for Node-REDの利用方法と開発について
404background
0
170
Make SRE Operations Easier with Azure SRE Agent
kkamegawa
0
5.1k
Semantic Version 単位で戦略を柔軟に変えて、パッケージアップデートを自動化する
daitasu
0
200
Observability in Practice:Grafana 與 Edge Device SRE 的那些事
blueswen
0
150
LLMによるContent Moderationの本番運用の裏側と品質担保への挑戦
suikabar
2
270
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
240
過去最大のMCPアップデート! 2026-07-28 RC版の謎に迫る
licux
6
210
LLM本来の能力を解き放つサンドボックス技術とAI民主化への適用
yukukotani
3
3.5k
「AIで開発し、AIを届ける」をEvalでつなぐ 〜AIネイティブに始めるプロダクト開発の実践〜 / Connecting "Develop with AI, deliver AI" with Eval
rkaga
4
4.9k
ADKを使って簡単にAIエージェントを作ってみよう
k1mu21
0
250
AIチームを指揮するOSS「TAKT」活用術 / How to Use “TAKT,” an OSS Tool for Orchestrating AI Teams
nrslib
6
860
Featured
See All Featured
Exploring the relationship between traditional SERPs and Gen AI search
raygrieselhuber
PRO
2
4k
What Being in a Rock Band Can Teach Us About Real World SEO
427marketing
0
250
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
62
54k
The agentic SEO stack - context over prompts
schlessera
0
800
Side Projects
sachag
455
43k
Understanding Cognitive Biases in Performance Measurement
bluesmoon
32
2.9k
Agile that works and the tools we love
rasmusluckow
331
21k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
12
1.2k
Embracing the Ebb and Flow
colly
88
5.1k
The Success of Rails: Ensuring Growth for the Next 100 Years
eileencodes
47
8.2k
Rebuilding a faster, lazier Slack
samanthasiow
85
9.5k
Impact Scores and Hybrid Strategies: The future of link building
tamaranovitovic
0
300
Transcript
High performance git infrastructure with Go David Calavera Code Climate
None
2005
(╯°□°)╯︵ ┻━┻
2008
2010…
How do we make git faster?
* system(“git log …”) * Ruby for brevity
git fetch origin
None
github.com/libgit2/git2go Disclaimer: examples do not handle errors
// Load with side effects. // Initialize libgit2’s TLS: //
// func init() { // C.git_libgit2_init() // } // // Import package “git”, which is // not very goimports friendly. import “github.com/libgit2/git2go”
// Create a new repository. // Do not use a
working directory. path := “/var/git/repository” bare := true r, _ := git.InitRepository(path, bare) ! // Clone a repository. url := “git://github.com/golang/go” opts := git.CloneOptions{Bare: bare} r, _ := git.Clone(url, path, &opts)
// Create a new remote ref. name := “my-fork” url
:= “git://github.com/wadus/go” rm, _ := r.CreateRemote(name, url) ! // Fetch all refs from a remote. var refspecs []string rm.Fetch(refspecs, nil, nil)
// Search for objects. sha := “4c279186e24f7b3a59aa682a870747df6eaca013” oid := git.NewOid(sha)
! c, _ := r.LookupCommit(oid) b, _ := r.LookupBlob(oid) t, _ := r.LookupTree(oid) ! o, _ := r.Lookup(oid) fmt.Printf(“ %v\n”, o.Type())
// Read commit data. sha := “4c279186e24f7b3a59aa682a870747df6eaca013” oid := git.NewOid(sha)
path := “src/os/exec.go” ! c, _ := r.LookupCommit(oid) t, _ := c.Tree() e, _ := t.EntryByPath(path) ! b, _ := r.LookupBlob(e.Id()) fmt.Printf(“ %q\n”, b.Contents())
// Commit new changes. idx, _ := r.Index() idx.AddByPath(“src/os/exec.go”) t,
_ := idx.WriteTree() idx.Write() ! h, _ := r.Head() c, _ := r.LookupCommit(h) ! s := &git.Signature{“me”, “
[email protected]
”, time.Now()} m := “Add moar changes” r.CreateCommit(“”, s, s, m, t, c)
None
None
Designing a distributed git storage
Application Git Service
Constraint your data model
// protocol buffers schema. message Branch { required string name
= 1; } ! message Repository { optional string name = 1; repeated Branch branches = 2; }
// Read branches. var branches []*pb.Branch ! f := func(b
*git.Branch, t git.BranchType) error { n, _ := b.Name() p := &pb.Branch{ Name: &n, } branches = append(branches, p) return nil } ! b, _ := r.NewBranchIterator(git.BranchRemote) b.ForEach(f)
// Read branches via http. h := func(w http.ResponseWriter, r
*http.Request) { pbBranches := readBranches(r) pbRepo := &pb.Repository{ Branches: pbBranches, } ! data, _ := proto.Marshal(pbRepo) w.Write(data) } ! http.HandleFunc(“/r/foo/branches”, h)
Design from first principles
A shared-data system can have at most two of the
three following properties: Consistency, Availability, and tolerance to network Partitions Dr. Eric Brewer
You Can’t Sacrifice Partition Tolerance Coda Hale
github.com/afex/hystrix-go" github.com/rubyist/circuitbreaker" github.com/eapache/go-resiliency/braker
// Read branches via http. import “github.com/rubyist/circuitbreaker” ! out :=
5 * time.Second url := “http://git-server/r/foo/branches” c := circuit.NewHTTPClient(out, 10, nil) ! c.BreakerTripped = func() { // Handle partition error response. } ! resp, _ := c.Get(url)
Replication Consistency Vs Availability
Application Git Service Git Service Primary Replica
Application Git Service Git Service Primary Replica Fetch!
Application Git Service Git Service Primary Replica Fetch!
Application Git Service Git Service Primary Replica Done!
Application Git Service Git Service Primary Replica Done!
// Handle fetch requests. h := func(w http.ResponseWriter, r *http.Request)
{ peerChannel := replicateRequest(r) rm, _ := repo.LoadRemote(“origin”) var refspecs []string rm.Fetch(refspecs, nil, nil) ! if peersChannel != nil { waitForPeers(peerChannel) } w.WriteHeader(201) } ! http.HandleFunc(“/r/foo/fetch”, h)
// Replicate request. func replicateRequest(r *http.Request) chan int { if
req.Header.Get(“X-GIT-REPLICATE”) != “” { return nil } peerChannel := make(chan int) replicaURL, err := url.Parse(replicaHost) replicaURL.Path = r.Path replicaURL.Header.Set(“X-GIT-REPLICATE”, “true") req, _ := http.NewRequest(“POST”, replicaURL.String(), nil) ! go func() { resp, _ := httpClient.Do(req) peerChannel <- resp.StatusCode }() return peerChannel }
// Wait for replica response. func waitForPeers(channel chan int) error
{ replicaStatus := <- channel switch replicaStatus { case 201: // default: // ☔️ ☔️ } ! return nil }
git architectures are fun
Thank you! @calavera