github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/mongo/writeconcern/writeconcern.go (about) 1 // Copyright (C) MongoDB, Inc. 2017-present. 2 // 3 // Licensed under the Apache License, Version 2.0 (the "License"); you may 4 // not use this file except in compliance with the License. You may obtain 5 // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 6 7 // Package writeconcern defines write concerns for MongoDB operations. 8 // 9 // For more information about MongoDB write concerns, see 10 // https://www.mongodb.com/docs/manual/reference/write-concern/ 11 package writeconcern // import "go.mongodb.org/mongo-driver/mongo/writeconcern" 12 13 import ( 14 "errors" 15 "fmt" 16 "time" 17 18 "go.mongodb.org/mongo-driver/bson" 19 "go.mongodb.org/mongo-driver/bson/bsontype" 20 "go.mongodb.org/mongo-driver/x/bsonx/bsoncore" 21 ) 22 23 const majority = "majority" 24 25 // ErrInconsistent indicates that an inconsistent write concern was specified. 26 // 27 // Deprecated: ErrInconsistent will be removed in Go Driver 2.0. 28 var ErrInconsistent = errors.New("a write concern cannot have both w=0 and j=true") 29 30 // ErrEmptyWriteConcern indicates that a write concern has no fields set. 31 // 32 // Deprecated: ErrEmptyWriteConcern will be removed in Go Driver 2.0. 33 var ErrEmptyWriteConcern = errors.New("a write concern must have at least one field set") 34 35 // ErrNegativeW indicates that a negative integer `w` field was specified. 36 // 37 // Deprecated: ErrNegativeW will be removed in Go Driver 2.0. 38 var ErrNegativeW = errors.New("write concern `w` field cannot be a negative number") 39 40 // ErrNegativeWTimeout indicates that a negative WTimeout was specified. 41 // 42 // Deprecated: ErrNegativeWTimeout will be removed in Go Driver 2.0. 43 var ErrNegativeWTimeout = errors.New("write concern `wtimeout` field cannot be negative") 44 45 // A WriteConcern defines a MongoDB read concern, which describes the level of acknowledgment 46 // requested from MongoDB for write operations to a standalone mongod, to replica sets, or to 47 // sharded clusters. 48 // 49 // For more information about MongoDB write concerns, see 50 // https://www.mongodb.com/docs/manual/reference/write-concern/ 51 type WriteConcern struct { 52 // W requests acknowledgment that the write operation has propagated to a 53 // specified number of mongod instances or to mongod instances with 54 // specified tags. It sets the the "w" option in a MongoDB write concern. 55 // 56 // W values must be a string or an int. 57 // 58 // Common values are: 59 // - "majority": requests acknowledgment that write operations have been 60 // durably committed to the calculated majority of the data-bearing 61 // voting members. 62 // - 1: requests acknowledgment that write operations have been written 63 // to 1 node. 64 // - 0: requests no acknowledgment of write operations 65 // 66 // For more information about the "w" option, see 67 // https://www.mongodb.com/docs/manual/reference/write-concern/#w-option 68 W interface{} 69 70 // Journal requests acknowledgment from MongoDB that the write operation has 71 // been written to the on-disk journal. It sets the "j" option in a MongoDB 72 // write concern. 73 // 74 // For more information about the "j" option, see 75 // https://www.mongodb.com/docs/manual/reference/write-concern/#j-option 76 Journal *bool 77 78 // WTimeout specifies a time limit for the write concern. It sets the 79 // "wtimeout" option in a MongoDB write concern. 80 // 81 // It is only applicable for "w" values greater than 1. Using a WTimeout and 82 // setting Timeout on the Client at the same time will result in undefined 83 // behavior. 84 // 85 // For more information about the "wtimeout" option, see 86 // https://www.mongodb.com/docs/manual/reference/write-concern/#wtimeout 87 WTimeout time.Duration 88 } 89 90 // Unacknowledged returns a WriteConcern that requests no acknowledgment of 91 // write operations. 92 // 93 // For more information about write concern "w: 0", see 94 // https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-writeconcern.-number- 95 func Unacknowledged() *WriteConcern { 96 return &WriteConcern{W: 0} 97 } 98 99 // W1 returns a WriteConcern that requests acknowledgment that write operations 100 // have been written to memory on one node (e.g. the standalone mongod or the 101 // primary in a replica set). 102 // 103 // For more information about write concern "w: 1", see 104 // https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-writeconcern.-number- 105 func W1() *WriteConcern { 106 return &WriteConcern{W: 1} 107 } 108 109 // Journaled returns a WriteConcern that requests acknowledgment that write 110 // operations have been written to the on-disk journal on MongoDB. 111 // 112 // The database's default value for "w" determines how many nodes must write to 113 // their on-disk journal before the write operation is acknowledged. 114 // 115 // For more information about write concern "j: true", see 116 // https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-ournal 117 func Journaled() *WriteConcern { 118 journal := true 119 return &WriteConcern{Journal: &journal} 120 } 121 122 // Majority returns a WriteConcern that requests acknowledgment that write 123 // operations have been durably committed to the calculated majority of the 124 // data-bearing voting members. 125 // 126 // Write concern "w: majority" typically requires write operations to be written 127 // to the on-disk journal before they are acknowledged, unless journaling is 128 // disabled on MongoDB or the "writeConcernMajorityJournalDefault" replica set 129 // configuration is set to false. 130 // 131 // For more information about write concern "w: majority", see 132 // https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-writeconcern.-majority- 133 func Majority() *WriteConcern { 134 return &WriteConcern{W: majority} 135 } 136 137 // Custom returns a WriteConcern that requests acknowledgment that write 138 // operations have propagated to tagged members that satisfy the custom write 139 // concern defined in "settings.getLastErrorModes". 140 // 141 // For more information about custom write concern names, see 142 // https://www.mongodb.com/docs/manual/reference/write-concern/#mongodb-writeconcern-writeconcern.-custom-write-concern-name- 143 func Custom(tag string) *WriteConcern { 144 return &WriteConcern{W: tag} 145 } 146 147 // Option is an option to provide when creating a WriteConcern. 148 // 149 // Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. 150 // For example: 151 // 152 // writeconcern.Majority() 153 // 154 // or 155 // 156 // journal := true 157 // &writeconcern.WriteConcern{ 158 // W: 2, 159 // Journal: &journal, 160 // } 161 type Option func(concern *WriteConcern) 162 163 // New constructs a new WriteConcern. 164 // 165 // Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. 166 // For example: 167 // 168 // writeconcern.Majority() 169 // 170 // or 171 // 172 // journal := true 173 // &writeconcern.WriteConcern{ 174 // W: 2, 175 // Journal: &journal, 176 // } 177 func New(options ...Option) *WriteConcern { 178 concern := &WriteConcern{} 179 180 for _, option := range options { 181 option(concern) 182 } 183 184 return concern 185 } 186 187 // W requests acknowledgement that write operations propagate to the specified number of mongod 188 // instances. 189 // 190 // Deprecated: Use the Unacknowledged or W1 functions or define a struct literal instead. 191 // For example: 192 // 193 // writeconcern.Unacknowledged() 194 // 195 // or 196 // 197 // journal := true 198 // &writeconcern.WriteConcern{ 199 // W: 2, 200 // Journal: &journal, 201 // } 202 func W(w int) Option { 203 return func(concern *WriteConcern) { 204 concern.W = w 205 } 206 } 207 208 // WMajority requests acknowledgement that write operations propagate to the majority of mongod 209 // instances. 210 // 211 // Deprecated: Use [Majority] instead. 212 func WMajority() Option { 213 return func(concern *WriteConcern) { 214 concern.W = majority 215 } 216 } 217 218 // WTagSet requests acknowledgement that write operations propagate to the specified mongod 219 // instance. 220 // 221 // Deprecated: Use [Custom] instead. 222 func WTagSet(tag string) Option { 223 return func(concern *WriteConcern) { 224 concern.W = tag 225 } 226 } 227 228 // J requests acknowledgement from MongoDB that write operations are written to 229 // the journal. 230 // 231 // Deprecated: Use the Journaled function or define a struct literal instead. 232 // For example: 233 // 234 // writeconcern.Journaled() 235 // 236 // or 237 // 238 // journal := true 239 // &writeconcern.WriteConcern{ 240 // W: 2, 241 // Journal: &journal, 242 // } 243 func J(j bool) Option { 244 return func(concern *WriteConcern) { 245 // To maintain backward compatible behavior (now that the J field is a 246 // bool pointer), only set a value for J if the input is true. If the 247 // input is false, do not set a value, which omits "j" from the 248 // marshaled write concern. 249 if j { 250 concern.Journal = &j 251 } 252 } 253 } 254 255 // WTimeout specifies a time limit for the write concern. 256 // 257 // It is only applicable for "w" values greater than 1. Using a WTimeout and setting Timeout on the 258 // Client at the same time will result in undefined behavior. 259 // 260 // Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. 261 // For example: 262 // 263 // wc := writeconcern.W1() 264 // wc.WTimeout = 30 * time.Second 265 // 266 // or 267 // 268 // journal := true 269 // &writeconcern.WriteConcern{ 270 // W: "majority", 271 // WTimeout: 30 * time.Second, 272 // } 273 func WTimeout(d time.Duration) Option { 274 return func(concern *WriteConcern) { 275 concern.WTimeout = d 276 } 277 } 278 279 // MarshalBSONValue implements the bson.ValueMarshaler interface. 280 // 281 // Deprecated: Marshaling a WriteConcern to BSON will not be supported in Go 282 // Driver 2.0. 283 func (wc *WriteConcern) MarshalBSONValue() (bsontype.Type, []byte, error) { 284 if wc == nil { 285 return 0, nil, ErrEmptyWriteConcern 286 } 287 288 var elems []byte 289 if wc.W != nil { 290 // Only support string or int values for W. That aligns with the 291 // documentation and the behavior of other functions, like Acknowledged. 292 switch w := wc.W.(type) { 293 case int: 294 if w < 0 { 295 return 0, nil, ErrNegativeW 296 } 297 298 // If Journal=true and W=0, return an error because that write 299 // concern is ambiguous. 300 if wc.Journal != nil && *wc.Journal && w == 0 { 301 return 0, nil, ErrInconsistent 302 } 303 304 elems = bsoncore.AppendInt32Element(elems, "w", int32(w)) 305 case string: 306 elems = bsoncore.AppendStringElement(elems, "w", w) 307 default: 308 return 0, 309 nil, 310 fmt.Errorf("WriteConcern.W must be a string or int, but is a %T", wc.W) 311 } 312 } 313 314 if wc.Journal != nil { 315 elems = bsoncore.AppendBooleanElement(elems, "j", *wc.Journal) 316 } 317 318 if wc.WTimeout < 0 { 319 return 0, nil, ErrNegativeWTimeout 320 } 321 322 if wc.WTimeout != 0 { 323 elems = bsoncore.AppendInt64Element(elems, "wtimeout", int64(wc.WTimeout/time.Millisecond)) 324 } 325 326 if len(elems) == 0 { 327 return 0, nil, ErrEmptyWriteConcern 328 } 329 return bson.TypeEmbeddedDocument, bsoncore.BuildDocument(nil, elems), nil 330 } 331 332 // AcknowledgedValue returns true if a BSON RawValue for a write concern represents an acknowledged write concern. 333 // The element's value must be a document representing a write concern. 334 // 335 // Deprecated: AcknowledgedValue will not be supported in Go Driver 2.0. 336 func AcknowledgedValue(rawv bson.RawValue) bool { 337 doc, ok := bsoncore.Value{Type: rawv.Type, Data: rawv.Value}.DocumentOK() 338 if !ok { 339 return false 340 } 341 342 val, err := doc.LookupErr("w") 343 if err != nil { 344 // key w not found --> acknowledged 345 return true 346 } 347 348 i32, ok := val.Int32OK() 349 if !ok { 350 return false 351 } 352 return i32 != 0 353 } 354 355 // Acknowledged indicates whether or not a write with the given write concern will be acknowledged. 356 func (wc *WriteConcern) Acknowledged() bool { 357 // Only {w: 0} or {w: 0, j: false} are an unacknowledged write concerns. All other values are 358 // acknowledged. 359 return wc == nil || wc.W != 0 || (wc.Journal != nil && *wc.Journal) 360 } 361 362 // IsValid returns true if the WriteConcern is valid. 363 func (wc *WriteConcern) IsValid() bool { 364 if wc == nil { 365 return true 366 } 367 368 switch w := wc.W.(type) { 369 case int: 370 // A write concern with {w: int} must have a non-negative value and 371 // cannot have the combination {w: 0, j: true}. 372 return w >= 0 && (w > 0 || wc.Journal == nil || !*wc.Journal) 373 case string, nil: 374 // A write concern with {w: string} or no w specified is always valid. 375 return true 376 default: 377 // A write concern with an unsupported w type is not valid. 378 return false 379 } 380 } 381 382 // GetW returns the write concern w level. 383 // 384 // Deprecated: Use the WriteConcern.W field instead. 385 func (wc *WriteConcern) GetW() interface{} { 386 return wc.W 387 } 388 389 // GetJ returns the write concern journaling level. 390 // 391 // Deprecated: Use the WriteConcern.Journal field instead. 392 func (wc *WriteConcern) GetJ() bool { 393 // Treat a nil Journal as false. That maintains backward compatibility with the existing 394 // behavior of GetJ where unset is false. If users want the real value of Journal, they can 395 // access the Journal field. 396 return wc.Journal != nil && *wc.Journal 397 } 398 399 // GetWTimeout returns the write concern timeout. 400 // 401 // Deprecated: Use the WriteConcern.WTimeout field instead. 402 func (wc *WriteConcern) GetWTimeout() time.Duration { 403 return wc.WTimeout 404 } 405 406 // WithOptions returns a copy of this WriteConcern with the options set. 407 // 408 // Deprecated: Use the WriteConcern convenience functions or define a struct literal instead. 409 // For example: 410 // 411 // writeconcern.Majority() 412 // 413 // or 414 // 415 // journal := true 416 // &writeconcern.WriteConcern{ 417 // W: 2, 418 // Journal: &journal, 419 // } 420 func (wc *WriteConcern) WithOptions(options ...Option) *WriteConcern { 421 if wc == nil { 422 return New(options...) 423 } 424 newWC := &WriteConcern{} 425 *newWC = *wc 426 427 for _, option := range options { 428 option(newWC) 429 } 430 431 return newWC 432 } 433 434 // AckWrite returns true if a write concern represents an acknowledged write 435 // 436 // Deprecated: Use [WriteConcern.Acknowledged] instead. 437 func AckWrite(wc *WriteConcern) bool { 438 return wc == nil || wc.Acknowledged() 439 }