Class: EditMediator::UpdateThread

Inherits:
Object
  • Object
show all
Defined in:
frontend/app/models/edit_mediator.rb

Constant Summary

SYNC_WITH_BACKEND_SECONDS =

We send our local copy of the active edits table to the backend periodically. Set this the same as the client’s INTERVAL_PERIOD so we don’t add too much delay to a client’s update hitting the backend.

10

Instance Method Summary (collapse)

Constructor Details

- (UpdateThread) initialize(active_edits, queue)

Returns a new instance of UpdateThread



49
50
51
52
# File 'frontend/app/models/edit_mediator.rb', line 49

def initialize(active_edits, queue)
  @active_edits = active_edits
  @queue = queue
end

Instance Method Details

- (Object) log_in_to_backend(force = false)



65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
# File 'frontend/app/models/edit_mediator.rb', line 65

def (force = false)
  @backend_session = nil if force

  if !@backend_session
    response = JSONModel::HTTP.post_form("/users/#{AppConfig[:staff_username]}/login",
                                         {
                                           "expiring" => "false",
                                           "password" => AppConfig[:staff_user_secret]
                                         })

    auth = ASUtils.json_parse(response.body)

    @backend_session = auth['session']
  end

  @backend_session
end

- (Object) record_update_locally(user, uri, last_report_time)



55
56
57
58
59
60
61
62
# File 'frontend/app/models/edit_mediator.rb', line 55

def record_update_locally(user, uri, last_report_time)
  @active_edits.update {|edits|
    entry = edits[uri] ? edits[uri].clone : {'edited_by' => {}}
    entry['edited_by'][user] = last_report_time

    edits.merge(uri => entry)
  }
end

- (Object) start



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
# File 'frontend/app/models/edit_mediator.rb', line 108

def start

  # The main thread: respond to updates and manage the local editing state.
  Thread.new do
    while true
      begin
        request = @queue.pop

        if request[:type] == :update
          self.record_update_locally(*request[:values])
        elsif request[:type] == :sync
          self.synchronise_with_backend
        end
      rescue
        $stderr.puts("ERROR: Edit mediator: #{$!}: #{$@}")
        sleep 5
      end
    end
  end


  # A separate thread to trigger a sync with the backend every now and then.
  Thread.new do
    while true
      sleep SYNC_WITH_BACKEND_SECONDS
      @queue << {:type => :sync}
    end
  end

end

- (Object) synchronise_with_backend



84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
# File 'frontend/app/models/edit_mediator.rb', line 84

def synchronise_with_backend
  snapshot = @active_edits.value
  edits = JSONModel(:active_edits).new

  edits.active_edits = snapshot.map {|uri, entries|
    entries['edited_by'].map {|user, last_time|
      {
        'uri' => uri,
        'user' => user,
        'time' => last_time,
      }
    }
  }.flatten(1)

  JSONModel::HTTP.current_backend_session = 

  begin
    updated = edits.save({}, true)
    @active_edits.update {|old_val| updated}
  rescue AccessDeniedException
    (true)
  end
end