[GODRIVER-2034] API Consistency for read/write Created: 02/Jun/21  Updated: 03/Jun/21  Resolved: 02/Jun/21

Status: Closed
Project: Go Driver
Component/s: Options & Configuration
Affects Version/s: 1.5.2, 1.5.3
Fix Version/s: None

Type: Improvement Priority: Unknown
Reporter: Matt Hartstonge Assignee: Isabella Siu (Inactive)
Resolution: Duplicate Votes: 0
Labels: None
Remaining Estimate: Not Specified
Time Spent: Not Specified
Original Estimate: Not Specified

Issue Links:
Documented
Duplicate
duplicates GODRIVER-964 make option type construction consist... Closed
Documentation Changes: Not Needed
Documentation Changes Summary:
  • Would be part of the auto generation Go docs.
  • May need to ensure any other documentation is up to date.

 Description   

While playing around with `mongo.readconcern` and `mongo.writeconcern` I noticed the API is different between the two modules. It would be nice if they aligned.

Currently, in order to obtain the best practise causal consistency, you have to use:

import (
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
 
func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.Majority()).
		SetDefaultWriteConcern(writeconcern.New(writeconcern.WMajority()))
}

First step I tried:

import (
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
 
func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.Majority()).
		SetDefaultWriteConcern(writeconcern.WMajority())
}

Which fails as `WMajority()` returns a `writeconcern.Option`. Which has to be passed into New.

So the second thing I tried to make the API look consistent was:

import (
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
 
func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.New(readconcern.Majority())).
		SetDefaultWriteConcern(writeconcern.New(writeconcern.WMajority()))
}

 Which naturally fails, as `readconcern.Majority()` returns a `*ReadConcern` rather than a `readconcern.Option`.

So you end up having to do this: 

import (
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
 
func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.New(readconcern.Level("majority"))).
		SetDefaultWriteConcern(writeconcern.New(writeconcern.WMajority()))
}

So it would be nice to be able to have `func Majority() *WriteConcern {}` being a function, like in `readconcern` that directly returns a `*Writeconcern` for API consistency/better developer experiance: 

import (
	"go.mongodb.org/mongo-driver/mongo/options"
	"go.mongodb.org/mongo-driver/mongo/readconcern"
	"go.mongodb.org/mongo-driver/mongo/writeconcern"
)
 
func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.Majority()).
		SetDefaultWriteConcern(writeconcern.Majority())
}

 

 



 Comments   
Comment by Matt Hartstonge [ 03/Jun/21 ]

Makes sense 😃
Thanks! 👍

For v2.0 - As a suggestion, I've noticed a common community pattern is to prepend variadic options with "With" so you would end up with:

func main() {
	opts := options.Session().
		SetCausalConsistency(true).
		SetDefaultReadConcern(readconcern.New(readconcern.WithLinearizable())).
		SetDefaultWriteConcern(writeconcern.New(
				writeconcern.WithWMajority(), 
				writeconcern.WithTimeout(time.Second*2),
		))
}

Comment by Isabella Siu (Inactive) [ 03/Jun/21 ]

Hi matt@linc-ed.com

Unfortunately, that would still be somewhat syntactically strange, as we wouldn't be able to do a corresponding writeconcern.W method. We do have plans to revisit this API when we do a 2.0 and can redo it completely.

Comment by Matt Hartstonge [ 03/Jun/21 ]

Hey @Isabella,

Surely this could be implemented really easily without breaking API changes by adding the following function into: "go.mongodb.org/mongo-driver/mongo/writeconcern" ?

This performs the same function wrapping that read concern does, but still leaves the `New(options...)` API open for detailed setting of write concerns based on w/j/tagset e.t.c.

// Majority specifies that that write operations should propagate to the 
// majority of members in the replica set.
func Majority() *WriteConcern {
   return New(WMajority())
}

 

 This small change would then bring `writeconcern` in line with `readpref` and `readconcern`.

Comment by Isabella Siu (Inactive) [ 02/Jun/21 ]

Hi matt@linc-ed.com!

Thanks for your improvement request! We agree that it would be better for readconcern, writeconcern, and readpref to have more consistent API, unfortunately the lack of function overloading in Go means that we would need to release a 2.0 version in order to match them more closely.

Generated at Thu Feb 08 08:37:41 UTC 2024 using Jira 9.7.1#970001-sha1:2222b88b221c4928ef0de3161136cc90c8356a66.