Upgrade to Pro — share decks privately, control downloads, hide ads and more …

On Ferrets and Gophers

On Ferrets and Gophers

MongoDB was a life-changing technology for many developers with its smooth UX. Unfortunately, reliability and real-life performance were lacking for a long time, and a license change made it unsuitable for many companies and projects. In my talk, I will introduce FerretDB – an open-source proxy between MongoDB drivers and PostgreSQL. It is built using Go 1.18 to benefit from type parameters (generics) and fuzzing, and I will show how they are useful already.

Alexey Palazhchenko

January 12, 2022
Tweet

More Decks by Alexey Palazhchenko

Other Decks in Programming

Transcript

  1. MongoDB • Great Developer Experience • Used to send iPads

    to community members • Reliability • Performance
  2. MongoDB • Great Developer Experience • Used to send iPads

    to community members • Reliability • Performance • Scalability
  3. MongoDB • Great Developer Experience • Used to send iPads

    to community members • Reliability • Performance • Scalability
  4. MongoDB • Great Developer Experience • Used to send iPads

    to community members • Reliability • Performance • Scalability • … does too much?
  5. MongoDB • Great Developer Experience • Used to send iPads

    to community members • Reliability • Performance • Scalability • … does too much? • License change
  6. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» SSPL
  7. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term SSPL
  8. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» SSPL
  9. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» SSPL
  10. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» • «If you make the functionality of the Program» SSPL
  11. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» • «If you make the functionality of the Program» • «available to third parties as a service» SSPL
  12. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» • «If you make the functionality of the Program» • «available to third parties as a service» • «includes, without limitation, […]»
 very broad, but not very clear SSPL
  13. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» • «If you make the functionality of the Program» • «available to third parties as a service» • «includes, without limitation, […]»
 very broad, but not very clear • «Service Source Code» SSPL
  14. AGPL v3 • «If you modify the Program» • «All

    users interacting with it remotely through a computer network» • «Interacting» is not a term • «Corresponding Source» • «Including scripts to control those activities» • «If you make the functionality of the Program» • «available to third parties as a service» • «includes, without limitation, […]»
 very broad, but not very clear • «Service Source Code» • «including, without limitation, management software, user interfaces, application program interfaces, […], all such that a user could run an instance of the service using the Service Source Code you make available.» SSPL
  15. FerretDB • MongoDB protocol proxy for PostgreSQL • Accepts unmodi

    fi ed client connections • Parses BSON queries
  16. FerretDB • MongoDB protocol proxy for PostgreSQL • Accepts unmodi

    fi ed client connections • Parses BSON queries • Converts them to SQL
  17. FerretDB • MongoDB protocol proxy for PostgreSQL • Accepts unmodi

    fi ed client connections • Parses BSON queries • Converts them to SQL • Sends them to PostgreSQL
  18. FerretDB • MongoDB protocol proxy for PostgreSQL • Accepts unmodi

    fi ed client connections • Parses BSON queries • Converts them to SQL • Sends them to PostgreSQL • Apache 2.0 licensed
  19. Generics • Generics do not work there; let's go back

    to interfaces • Let me extract a small example for meetup
  20. Generics • Generics do not work there; let's go back

    to interfaces • Let me extract a small example for meetup • Hm, that's not that bad
  21. BSON Document • Ordered map • Keys – string, values

    – any BSON value, including other documents
  22. BSON Document • Ordered map • Keys – string, values

    – any BSON value, including other documents • The central data structure in FerretDB
  23. Interfaces type BSONType interface { bsontype() // sealed } type

    Int int func (Int) bsontype() {} type String string func (String) bsontype() {}
  24. Interfaces type BSONType interface { bsontype() // sealed } type

    Int int func (Int) bsontype() {} type String string func (String) bsontype() {} type Document struct { m map[string]BSONType keys []string } func (*Document) bsontype() {}
  25. Interfaces func (d *Document) Set(key string, value BSONType) { if

    _, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value }
  26. Generics type BSONType interface { int | string | *Document

    } type Document struct { m map[string]any keys []string }
  27. Generics func DocumentSet[T BSONType](d *Document, key string, value T) {

    if _, ok := d.m[key]; !ok { d.keys = append(d.keys, key) } d.m[key] = value }
  28. Interfaces func MakeDocument(pairs ...BSONType) (*Document, error) { l := len(pairs)

    if l%2 != 0 { return nil, fmt.Errorf("%d arguments", l)
  29. Generics func MakeDocument[T BSONType](key string, value T) *Document func MakeDocument2[T1,

    T2 BSONType](key1 string, value1 T1, key2 string, value2 T2) *Document
  30. Generics func MakeDocument[T BSONType](key string, value T) *Document func MakeDocument2[T1,

    T2 BSONType](key1 string, value1 T1, key2 string, value2 T2) *Document func MakeDocument3[T1, T2, T3 BSONType](key1 string, value1 T1, key2 string, value2 T2, key3 string, value3 T3) *Document
  31. Generics vs Interfaces • Better in some aspects • Worse

    in others • https://github.com/AlekSi/generics-vs-interfaces
  32. Fuzzing • testing/quick on steroids • https://go.dev/blog/fuzz-beta • MongoDB binary

    protocol parsing packages • They had fuzzing tests even before unit tests
  33. Fuzzing func fuzzBSON(f *testing.F, tcs []testCase, newF func() BSONType) {

    for _, tc := range tcs { f.Add(tc.b) } // f.Run(tc.name, func(t *testing.T) f.Fuzz(func(t *testing.T, b []byte) {
  34. Fuzzing func fuzzBSON(f *testing.F, tcs []testCase, newF func() BSONType) {

    for _, tc := range tcs { f.Add(tc.b) } // f.Run(tc.name, func(t *testing.T) f.Fuzz(func(t *testing.T, b []byte) { https://github.com/golang/go/issues/47413 👍
  35. Back to FerretDB • Can't wait for Go 1.18 release

    to make it easier for contributors
  36. Back to FerretDB • Can't wait for Go 1.18 release

    to make it easier for contributors • Speaking of contributors – our community is awesome!
  37. Back to FerretDB • Can't wait for Go 1.18 release

    to make it easier for contributors • Speaking of contributors – our community is awesome! • And FerretDB Inc. started hiring about 1 hour ago