Class: Tengine::Core::Event

Inherits:
Object
  • Object
show all
Includes:
Mongoid::Document, Mongoid::Timestamps, CollectionAccessible, SelectableAttr, Validation
Defined in:
lib/tengine/core/event.rb

Defined Under Namespace

Classes: Finder

Constant Summary

Constants included from Validation

Validation::BASE_NAME, Validation::EVENT_TYPE_NAME, Validation::RESOURCE_IDENTIFIER, Validation::RESOURCE_IDENTIFIER_PROTOCOL_FORMAT

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#kernelObject

tengined実行時に処理しているカーネルのインスタンスを保持します



57
58
59
# File 'lib/tengine/core/event.rb', line 57

def kernel
  @kernel
end

Class Method Details

.find_or_create_then_update_with_block(condition, retry_max = 60, wtimeout = 10240) {|event| ... } ⇒ Tengine::Core::Event

Returns The event in question if update succeeded, false if retry_max reached, or nil if the block exited with false.

Parameters:

  • condition (Hash)

    Criteria to find a document.

  • retry_max (Numeric) (defaults to: 60)

    (60) Maximum number of retry attempts to save the event.

  • wtimeout (Numeric) (defaults to: 10240)

    (10240) Write timeout, ignored for earlier mongodb.

Yields:

  • (event)

    Yields the (possibly new) event.

Yield Parameters:

Yield Returns:

  • (Boolean)

    Return false, and it will just break the execution. Otherwise, it tries to update the event.

Returns:

  • (Tengine::Core::Event)

    The event in question if update succeeded, false if retry_max reached, or nil if the block exited with false.

Raises:

  • (Mongo::OperationFailure)

    Any exceptions that happened inside will be propagated outside.



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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
# File 'lib/tengine/core/event.rb', line 76

def self.find_or_create_then_update_with_block condition, retry_max = 60, wtimeout = 10240
  # * とある条件を満たすイベントがあれば、それを上書きしたい。
  # * なければ、新規作成したい。
  # * でもアトミックにやりたい。
  # * ないとおもって新規作成しようとしたら裏でイベントが生えていたら、上書きモードでやり直したい。
  # * あるとおもって上書きしようとしたら裏でイベントが消えていたら、新規作成モードでやり直したい。
  # * という要求をできるだけ高速に処理したい。

  the_event = nil
  retries = -1
  results = nil

  safemode = Tengine::Core::SafeUpdatable.safemode(collection, wtimeout)

  while true do
    return false if retries >= retry_max # retryしすぎ

    retries += 1
    # あればとってくる
    if the_event and not the_event.new_record?
      the_event.reload
    else
      the_event = where(condition).first || new(condition)
    end

    return nil if not yield(the_event) # ユザーによる意図的な中断

    hash = the_event.as_document.dup # <- dup ?
    hash.delete "_id"
    hash['lock_version'] = the_event.lock_version + 1
    hash['created_at'] ||= Time.at(Time.now.to_i)
    hash['updated_at'] = Time.at(Time.now.to_i)

    results = nil
    begin
      # Can't, no results returned...
      # results = with(safe: safemode).where(
      #   key: the_event.key, lock_version: the_event.lock_version
      # ).update(
      #   "$set" => hash,
      #   flags: [ :upsert ]
      # )
      mongo_session.with(safe: safemode) do |ss|
        col = ss[collection.name]
        results = ss.context.update(
          col.database.name,
          col.name,
          { key: the_event.key, lock_version: the_event.lock_version },
          { "$set" => hash },
          flags: [ :upsert ]
        )
      end
    rescue Moped::Errors::OperationFailure => e
      # upsert = trueだがindexのunique制約があるので重複したkeyは
      # 作成不可、lock_versionの更新失敗はこちらに来る。これは意
      # 図した動作なのでraiseしない。
      Tengine.logger.debug "retrying due to mongodb error #{e}"
      # lock_versionが存在しない可能性(そのような古いDBを引きずっている等)
      mongo_session.with(safe: safemode) do |ss|
        col = ss[collection.name]
        results = ss.context.update(
          col.database.name,
          col.name,
          { "$query" => { key: the_event.key, lock_version: { "$exists" => false} } },
          { "$set" => { lock_version: -(2**63) } },
        )
      end
      # again
    else
      if results["error"]
        raise Moped::Errors::OperationFailure, results["error"]
      elsif results["upserted"]
        # *hack* _idを消してupsertしたので、このとき_idは新しくなっている
        the_event._id = results["upserted"]
        the_event.reload
        return the_event
      else
        the_event.reload
        return the_event
      end
    end
  end
rescue Exception
p $!
end

Instance Method Details

#to_hashObject



59
60
61
62
63
# File 'lib/tengine/core/event.rb', line 59

def to_hash
  ret = attributes.dup # <- dup ?
  ret.delete "_id"
  ret
end