File: cluster_time.rb

package info (click to toggle)
ruby-mongo 2.21.3-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 14,764 kB
  • sloc: ruby: 108,806; makefile: 5; sh: 2
file content (142 lines) | stat: -rw-r--r-- 4,643 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
# frozen_string_literal: true
# rubocop:todo all

# Copyright (C) 2019-2020 MongoDB Inc.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

module Mongo
  # ClusterTime encapsulates cluster time storage and operations.
  #
  # The primary operation performed on the cluster time is advancing it:
  # given another cluster time, pick the newer of the two.
  #
  # This class provides comparison methods that are used to figure out which
  # cluster time is newer, and provides diagnostics in lint mode when
  # the actual time is missing from a cluster time document.
  #
  # @api private
  class ClusterTime < BSON::Document
    def initialize(elements = nil)
      super

      if Lint.enabled? && !self['clusterTime']
        raise ArgumentError, 'Creating a cluster time without clusterTime field'
      end
    end

    # Advances the cluster time in the receiver to the cluster time in +other+.
    #
    # +other+ can be nil or be behind the cluster time in the receiver; in
    # these cases the receiver is returned unmodified. If receiver is advanced,
    # a new ClusterTime object is returned.
    #
    # Return value is nil or a ClusterTime instance.
    def advance(other)
      if self['clusterTime'] && other['clusterTime'] &&
        other['clusterTime'] > self['clusterTime']
      then
        ClusterTime[other]
      else
        self
      end
    end

    # Compares two ClusterTime instances by comparing their timestamps.
    def <=>(other)
      if self['clusterTime'] && other['clusterTime']
        self['clusterTime'] <=> other['clusterTime']
      elsif !self['clusterTime']
        raise ArgumentError, "Cannot compare cluster times when receiver is missing clusterTime key: #{inspect}"
      else other['clusterTime']
        raise ArgumentError, "Cannot compare cluster times when other is missing clusterTime key: #{other.inspect}"
      end
    end

    # Older Rubies do not implement other logical operators through <=>.
    # TODO revise whether these methods are needed when
    # https://jira.mongodb.org/browse/RUBY-1622 is implemented.
    def >=(other)
      (self <=> other) != -1
    end
    def >(other)
      (self <=> other) == 1
    end
    def <=(other)
      (self <=> other) != 1
    end
    def <(other)
      (self <=> other) == -1
    end

    # Compares two ClusterTime instances by comparing their timestamps.
    def ==(other)
      if self['clusterTime'] && other['clusterTime'] &&
        self['clusterTime'] == other['clusterTime']
      then
        true
      else
        false
      end
    end

    class << self
      # Converts a BSON::Document to a ClusterTime.
      #
      # +doc+ can be nil, in which case nil is returned.
      def [](doc)
        if doc.nil? || doc.is_a?(ClusterTime)
          doc
        else
          ClusterTime.new(doc)
        end
      end
    end

    # This module provides common cluster time tracking behavior.
    #
    # @note Although attributes and methods defined in this module are part of
    #   the public API for the classes including this module, the fact that
    #   the methods are defined on this module and not directly on the
    #   including classes is not part of the public API.
    module Consumer

      # The cluster time tracked by the object including this module.
      #
      # @return [ nil | ClusterTime ] The cluster time.
      #
      # Changed in version 2.9.0: This attribute became an instance of
      # ClusterTime, which is a subclass of BSON::Document.
      # Previously it was an instance of BSON::Document.
      #
      # @since 2.5.0
      attr_reader :cluster_time

      # Advance the tracked cluster time document for the object including
      # this module.
      #
      # @param [ BSON::Document ] new_cluster_time The new cluster time document.
      #
      # @return [ ClusterTime ] The resulting cluster time.
      #
      # @since 2.5.0
      def advance_cluster_time(new_cluster_time)
        if @cluster_time
          @cluster_time = @cluster_time.advance(new_cluster_time)
        else
          @cluster_time = ClusterTime[new_cluster_time]
        end
      end
    end
  end
end