seapig-rails 0.0.6 → 0.0.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 534372c316056968d765bff6ef7f1d41f2e93734
4
- data.tar.gz: 15aa1b58cb7309ebc2e72df46b198e6783448328
3
+ metadata.gz: 42061dcf4ac1f6917849a446a9c7c172d32410ab
4
+ data.tar.gz: 9e4b9e713cfe8beb6c219b488bb561df4e8a0af2
5
5
  SHA512:
6
- metadata.gz: 2f04cb720f9e68a5581898f38add51bd6ac177bb4478c53b58175e488a0dc52a42102a704c917d32ecf94d755f0fd052cd712dd7184a7044ea3d9442da1d8e02
7
- data.tar.gz: eaee9f1518774181cfeb2ea8d139838729735d8fe6e918379c75f0627a075a63b71cabc4fd34d3464b2dfcbe6005714fe904c2a74dc4409d84ef3153a9fac24b
6
+ metadata.gz: 00424c408f4db3d6a4ff1b9e609b70bc44518578013ac1af18cb363439f1462621b67f7e6527536e7ded8314dd40ce6fc4b4bc6231fddf2910e6d5db6113a6b7
7
+ data.tar.gz: b905c978f13c69f34395b5b80dca458a59424140370f54c57866f911a9bc9f95518fa72a2427b23e5a10e14d6c217c7726ea71a6209eab563b8151f69223c591
@@ -0,0 +1,153 @@
1
+ @e = (content)->
2
+ content.__seapig_binding_element__ = {
3
+ }
4
+ content
5
+
6
+
7
+ class @SeapigBinding
8
+
9
+
10
+ constructor: (seapig_server, options = {})->
11
+ @seapig_server = seapig_server
12
+ @debug = options.debug
13
+ @view(options.view) if options.view
14
+ @onchange = options.onchange
15
+ @valid = false
16
+ @initialized = false
17
+ @object = false
18
+ @object_id = null
19
+ @elements = null
20
+ @shadow = { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
21
+ @selector = (data) -> data
22
+ @model(options.model) if options.model?
23
+
24
+ state: (element)->
25
+
26
+ view: (view)->
27
+ $(document).on('click',view+' .seapig-binding-element-delete', (event) =>
28
+ console.log('BINDING: A-element clicked.',event) if @debug
29
+ element = @element_find(event.target)
30
+ @element_remove(element[0],element[1],$(dom_element).hasClass('seapig-bindind-autosave'))
31
+ false
32
+ )
33
+
34
+
35
+ #FIXME: OOize all element_* methods
36
+
37
+ element_remove: (parent,id,save)->
38
+ console.log("removing", parent, id) if @debug
39
+
40
+ element_find: (dom_element)->
41
+ path = []
42
+ while dom_element
43
+ id = $(dom_element).attr('data-seapig-binding-element')
44
+ path.push(id) if id
45
+ dom_element = dom_element.parentElement
46
+ path = path.reverse()
47
+ id = path.pop()
48
+ parent = @elements
49
+ for step in path
50
+ parent = parent[step]
51
+ [parent, id]
52
+
53
+
54
+ update_element: (elements, key, shadows, shadow_key, element, remote) ->
55
+ if typeof(remote) == "object"
56
+ if typeof(remote) == "undefined" #delete
57
+ delete elements[key]
58
+ delete shadows[shadow_key]
59
+ else
60
+ if (element? != remote?) or (typeof(element) != typeof(remote)) or (Array.isArray(element) != Array.isArray(remote)) #(re-)create
61
+ element = if remote == null then null else if Array.isArray(remote) then [] else {}
62
+ shadows[shadow_key] = { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
63
+ elements[key] = element
64
+ @update(elements[key],shadows[shadow_key],remote) if element? #update
65
+ else
66
+ if typeof(remote) == "undefined" #delete
67
+ delete elements[key]
68
+ delete shadows[shadow_key]
69
+ else #update
70
+ elements[key] = remote
71
+ if element != remote
72
+ shadows[shadow_key] ||= { __seapig_binding_element__: {state: {},conflict: {},updated_at: {}}}
73
+ shadows[shadow_key].__seapig_binding_element__.updated_at[key] = new Date()
74
+
75
+
76
+ update: (elements, shadow, remotes)->
77
+ throw "wut? a vampaya?" if not shadow?
78
+ console.log("updating",elements,shadow,remotes) if @debug
79
+
80
+
81
+ if Array.isArray(elements)
82
+ console.log('array') if @debug
83
+ elements_by_id = _.object(([(e? and e.id or i), e] for e,i in elements))
84
+ remotes_by_id = _.object(([(e? and e.id or i), e] for e,i in remotes))
85
+ shadow_shadow = _.object([k,v] for k,v of shadow)
86
+ console.log("elements_by_id, remotes_by_id", elements_by_id, remotes_by_id ) if @debug
87
+
88
+ added_elements = _.difference(_.keys(remotes_by_id),_.keys(elements_by_id))
89
+ removed_elements = _.difference(_.keys(elements_by_id),_.keys(remotes_by_id))
90
+ console.log("added", added_elements) if @debug
91
+ console.log("removed", removed_elements) if @debug
92
+ elements.length = 0
93
+ shadow.length = 0
94
+ for remote_element,i in remotes
95
+ id = (remote_element? and remote_element.id or i)
96
+ element = elements_by_id[id]
97
+ console.log('adding',remote_element,id,element) if @debug
98
+ @update_element(elements,i,shadow,id,element,remote_element)
99
+ console.log(elements) if @debug
100
+
101
+ else
102
+ console.log('object') if @debug
103
+ added_elements = _.difference(_.keys(remotes),_.keys(elements))
104
+ common_elements = _.intersection(_.keys(remotes),_.keys(elements))
105
+ removed_elements = _.difference(_.keys(elements),_.keys(remotes))
106
+ console.log("added", added_elements) if @debug
107
+ console.log("common", common_elements) if @debug
108
+ console.log("removed", removed_elements) if @debug
109
+
110
+ for element in added_elements
111
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
112
+
113
+ for element in removed_elements
114
+ switch shadow.__seapig_binding_element__.state[element]
115
+ when 'clean', undefined
116
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
117
+ else
118
+ console.log('filth! 1')
119
+
120
+ for element in common_elements
121
+ switch shadow.__seapig_binding_element__.state[element]
122
+ when 'clean', undefined
123
+ @update_element(elements,element,shadow,element,elements[element],remotes[element])
124
+ else
125
+ console.log('filth! 2')
126
+
127
+
128
+
129
+ model: (object_id)->
130
+ return if object_id == @object_id
131
+ @object_id = object_id
132
+
133
+ if @object
134
+ @object.unlink()
135
+ @valid = false
136
+ @initialized = false
137
+
138
+ if @object_id
139
+ @object = @seapig_server.slave(@object_id)
140
+ @object.onchange = ()=>
141
+ if @object.valid
142
+ console.log('BINDING: Data update received.') if @debug
143
+ new_elements = @selector(JSON.parse(JSON.stringify(@object.object)))
144
+ @elements ||= (if Array.isArray(new_elements) then [] else {})
145
+ @shadow ||= (if Array.isArray(new_elements) then [] else {})
146
+ @update(@elements,@shadow,new_elements)
147
+ @initialized = true
148
+ console.log(@elements) if @debug
149
+ @valid = @object.valid
150
+ @onchange() if @onchange
151
+ @data = @object.object
152
+
153
+ @onchange() if @onchange
@@ -22,6 +22,7 @@ class @SeapigServer
22
22
  console.log('Seapig connection closed') if @options.debug
23
23
  for object_id, object of @slave_objects
24
24
  object.valid = false
25
+ object.onchange() if object.onchange?
25
26
  setTimeout((=>@connect()), 2000)
26
27
 
27
28
  @socket.onopen = () =>
@@ -1,22 +1,26 @@
1
1
  class @SeapigRouter
2
2
 
3
3
 
4
- constructor: (seapig_server, session_id, initial_search, debug = false)->
4
+ constructor: (seapig_server, session_id, mountpoint, initial_search, debug = false)->
5
5
  @seapig_server = seapig_server
6
6
  @session_id = session_id
7
+ @mountpoint = mountpoint
7
8
  @debug = debug
8
9
  @initial_search = initial_search
9
10
 
10
11
  @state = {session_id: @session_id, id: 0}
12
+ @volatile = {}
11
13
 
12
14
  @session_data = @seapig_server.master('web-session-data-'+@session_id)
13
15
  @session_data.object.states = [ @state ]
14
16
  @session_data.sequence = 1
15
17
  @session_data.bases = {}
18
+ @session_data.diffs = {}
16
19
  @session_data.changed()
17
20
 
18
21
  @session_data_saved = @seapig_server.slave('web-session-saved-'+@session_id)
19
22
  @session_data_saved.onchange = ()=>
23
+ return if not @session_data_saved.valid
20
24
  while @session_data.object.states[0]? and @session_data.object.states[0].id < @session_data_saved.object.max_state_id
21
25
  @session_data.object.states.shift()
22
26
  console.log('Session saved, updating url:',@current_url()) if @debug
@@ -24,7 +28,6 @@ class @SeapigRouter
24
28
  window.history.replaceState(@state,null,@current_url()) if @state_valid
25
29
  @replacing_state = false
26
30
 
27
-
28
31
  @replacing_state = false
29
32
  @state_valid = false
30
33
 
@@ -37,77 +40,111 @@ class @SeapigRouter
37
40
  )
38
41
 
39
42
  window.onpopstate = (data) =>
43
+ previous_state = JSON.parse(JSON.stringify(@state))
40
44
  @state = data.state
41
- @state_changed()
42
-
45
+ @update_location()
46
+ @onstatechange(@state,previous_state) if @onstatechange?
43
47
 
44
48
 
45
- location_changed: () ->
46
- return if @replacing_state
47
- console.log('ROUTER: Location changed to: pathname:', window.location.pathname, ' search:', window.location.search) if @debug
48
-
49
- spl = window.location.pathname.split('/')
49
+ url_to_diff: (pathname, search)->
50
+ spl = pathname.split(@mountpoint)
50
51
  spl.shift()
52
+ spl = spl.join(@mountpoint).split('/')
51
53
  if spl.shift() == 'a'
52
54
  path_session_id = spl.shift()
53
55
  path_state_id = spl.shift()
54
56
  if not path_state_id
55
- window.history.replaceState(@state,null,'/a/'+@session_id+'/0'+window.location.search)
56
- return @location_changed()
57
+ return { replace: @mountpoint+'a/'+@session_id+'/0'+window.location.search }
57
58
  else
58
- window.history.replaceState(@state,null,'/a/'+@session_id+'/0?'+(@initial_search.replace(/^\?/,'')+window.location.search.replace(/^\?/,'&')).replace(/^&/,''))
59
- return @location_changed()
59
+ return { replace: @mountpoint+'a/'+@session_id+'/0?'+(@initial_search.replace(/^\?/,'')+window.location.search.replace(/^\?/,'&')).replace(/^&/,'') }
60
60
 
61
61
  total_diff = []
62
62
  partial_diff = []
63
63
  while spl.length > 0
64
64
  total_diff.push([spl.shift(),spl.shift()])
65
- if window.location.search.length > 0
66
- for pair in window.location.search.split('?')[1].split('&')
65
+ if search.length > 1
66
+ for pair in search.split('?')[1].split('&')
67
67
  total_diff.push(pair.split('=',2))
68
68
  partial_diff.push(pair.split('=',2))
69
+
69
70
  console.log('Parsed location: session_id:',path_session_id,' partial_diff:', partial_diff) if @debug
70
71
 
71
- if path_session_id == @session_id
72
- @state_change(partial_diff)
72
+ { total: total_diff, partial: partial_diff, session_id: path_session_id, state_id: path_state_id }
73
+
74
+
75
+ location_changed: () ->
76
+ return if @replacing_state
77
+ console.log('ROUTER: Location changed to: pathname:', window.location.pathname, ' search:', window.location.search) if @debug
78
+
79
+ diff = @url_to_diff(window.location.pathname,window.location.search)
80
+ if diff.replace?
81
+ console.log('ROUTER: Invalid url, replacing with:', diff.replace) if @debug
82
+ window.history.replaceState(@state,null,diff.replace)
83
+ return @location_changed()
84
+
85
+ if diff.session_id == @session_id
86
+ @state_change(diff.partial)
73
87
  else
74
88
  if @remote_state?
75
- @state_change_to_remote(total_diff)
89
+ @state_change_to_remote(diff.total) #oaueia
76
90
  else
77
91
  @state_valid = false
78
- if path_state_id == '0'
79
- @remote_state = {object: {session_id: path_session_id, id: 0}}
80
- @state_change_to_remote(total_diff)
92
+ if diff.state_id == '0'
93
+ @state = {session_id: diff.session_id, id: 0}
94
+ @state_change(diff.total)
81
95
  else
82
- @remote_state = @seapig_server.slave('web-session-state-'+path_session_id+':'+path_state_id)
83
- @remote_state.onchange = ()=> @state_change_to_remote(total_diff)
96
+ @remote_state = @seapig_server.slave('web-session-state-'+diff.session_id+':'+diff.state_id)
97
+ @remote_state.onchange = ()=>
98
+ return if not @remote_state.valid
99
+ @state = _.clone(@remote_state.object)
100
+ @state_change(diff.total)
101
+ @remote_state.unlink()
102
+ @remote_state = null
103
+
104
+
105
+ state_commit: () ->
106
+ if @state.uncommitted
107
+ console.log("Deferred commit") if @debug
108
+ delete @state.uncommitted
109
+ @session_data.object.states.push(@state)
110
+ @session_data.changed()
111
+ clearTimeout(@commit_timer) if @commit_timer
112
+ @commit_at = null
113
+ @commit_timer = null
114
+ @update_location()
84
115
 
85
116
 
86
- state_change_to_remote: (diff) ->
87
- @state = _.clone(@remote_state.object)
117
+ state_change: (diff,defer = 0) ->
118
+ commit_at = Date.now() + defer
119
+ previous_state = JSON.parse(JSON.stringify(@state))
88
120
  if diff.length > 0
89
- @state_change(diff)
90
- else
91
- #@session_data.object.states.push(@state)
92
- @state_valid = true
93
- @state_changed()
94
-
121
+ console.log("Applying change at:", defer, commit_at,"to",@state) if @debug
122
+ next_state = @state
123
+ if not @state.uncommitted?
124
+ base_state = @state
125
+ next_state = _.clone(@state)
126
+ next_state.session_id = @session_id
127
+ next_state.id = @session_data.sequence++
128
+ @session_data.bases[next_state.id] = base_state
129
+ @session_data.diffs[next_state.id] = []
130
+ next_state = @state_diff_apply(next_state, diff)
131
+ console.log("Pre-filter next-state", next_state)
132
+ @statefilter(next_state,previous_state) if @statefilter?
133
+ console.log("Post-filter next-state", next_state)
134
+ @state = next_state
135
+ @session_data.diffs[@state.id] = @session_data.diffs[@state.id].concat(diff)
136
+ if commit_at <= Date.now()
137
+ @state_commit()
138
+ else
139
+ @state.uncommitted = true
140
+ if (not @commit_at) or (commit_at < @commit_at)
141
+ console.log("Deferring commit by,till:", commit_at - Date.now(), commit_at) if @debug
142
+ clearTimeout(@commit_timer) if @commit_timer
143
+ @commit_at = commit_at
144
+ @commit_timer = setTimeout((()=> @state_commit()), @commit_at - Date.now())
95
145
 
96
- state_change: (diff) ->
97
- base_state = @state
98
- @state = @state_diff_apply(_.clone(@state), diff)
99
- @state.diff = diff
100
- @statefilter(@state) if @statefilter?
101
- @state.session_id = @session_id
102
- @state.id = @session_data.sequence++
103
- @session_data.bases[@state.id] = base_state
104
- @session_data.object.states.push(@state)
105
- @session_data.changed()
106
- if @remote_state?
107
- @remote_state.unlink() if @remote_state.object.id > 0
108
- @remote_state = null
109
146
  @state_valid = true
110
- @state_changed()
147
+ @onstatechange(@state,previous_state) if @onstatechange?
111
148
 
112
149
 
113
150
  state_diff_apply: (state, diff)->
@@ -128,12 +165,12 @@ class @SeapigRouter
128
165
  if hash
129
166
  obj[spl[spl.length-1]] = value
130
167
  else
131
- obj[spl[spl.length-1]].push(value)
168
+ (obj[spl[spl.length-1]] ||= []).push(value)
132
169
  else
133
170
  if hash
134
171
  delete obj[spl[spl.length-1]]
135
172
  else
136
- state[entry[0]].splice(_.indexOf(state[entry[0]], value),1)
173
+ obj[spl[spl.length-1]].splice(_.indexOf(obj[spl[spl.length-1]], value),1)
137
174
  state
138
175
 
139
176
 
@@ -151,17 +188,21 @@ class @SeapigRouter
151
188
  path_overlay = ""
152
189
  for state in chain
153
190
  console.log('-',state) if @debug
154
- path_overlay += @state_diff_to_path(state.diff)
155
-
156
- console.log('Calculated url:','/a/'+base_state.session_id+'/'+base_state.id+path_overlay) if @debug
157
- '/a/'+base_state.session_id+'/'+base_state.id+path_overlay
191
+ path_overlay += @state_diff_to_path(@session_data.diffs[state.id])
158
192
 
193
+ console.log('Calculated url:',@mountpoint+'a/'+base_state.session_id+'/'+base_state.id+path_overlay) if @debug
194
+ @mountpoint+'a/'+base_state.session_id+'/'+base_state.id+path_overlay
159
195
 
160
- state_changed: () ->
161
196
 
197
+ update_location: () ->
162
198
  console.log("ROUTER: State changed to: state:", @state, ' url:', @current_url()) if @debug
163
199
  @replacing_state = true
164
200
  window.history.replaceState(@state,null,@current_url())
165
201
  @replacing_state = false
166
202
 
167
- @onstatechange(@state) if @onstatechange?
203
+
204
+ stealth_change: (query, defer = 1000) ->
205
+ [pathname, search] = query.split("?")
206
+ pathname = window.location.pathname if pathname.length == 0
207
+ diff = @url_to_diff(pathname,"?"+(search or ""))
208
+ @state_change(diff.partial,defer)
@@ -0,0 +1,25 @@
1
+ class SeapigDependency < ActiveRecord::Base
2
+
3
+ def self.bump(*names) #FIXME: mass upsert / PG 9.5
4
+ self.transaction {
5
+ ret = names.map { |name|
6
+ value = self.find_by_sql(["UPDATE seapig_dependencies SET current_version = nextval('seapig_dependency_version_seq'), updated_at = now() WHERE name = ? RETURNING current_version", name])
7
+ value = self.find_by_sql(["INSERT INTO seapig_dependencies(name, current_version, reported_version, created_at, updated_at) VALUES (?,nextval('seapig_dependency_version_seq'),0,now(),now()) RETURNING current_version",name]) if value.size == 0
8
+ value[0].current_version
9
+ }
10
+ connection.instance_variable_get(:@connection).exec("NOTIFY seapig_dependency_changed")
11
+ }
12
+ end
13
+
14
+
15
+ def self.version(name)
16
+ self.versions(name)[name]
17
+ end
18
+
19
+
20
+ def self.versions(*names)
21
+ Hash[*self.find_by_sql(["SELECT names.name, COALESCE(sd.current_version,0) AS current_version FROM (SELECT unnest(ARRAY[?]) AS name) AS names LEFT OUTER JOIN seapig_dependencies AS sd ON names.name = sd.name", names]).map { |name| [name.name,name.current_version] }.flatten]
22
+ end
23
+
24
+
25
+ end
@@ -2,9 +2,6 @@ class SeapigRouterSession < ActiveRecord::Base
2
2
 
3
3
  has_many :seapig_router_session_states
4
4
 
5
- acts_as_seapig_dependency
6
-
7
-
8
5
  def self.generate
9
6
  session = SeapigRouterSession.new
10
7
  begin
@@ -2,6 +2,4 @@ class SeapigRouterSessionState < ActiveRecord::Base
2
2
 
3
3
  belongs_to :seapig_router_session
4
4
 
5
- acts_as_seapig_dependency
6
-
7
5
  end
data/bin/seapig-notifier CHANGED
@@ -1,36 +1,25 @@
1
1
  #!/bin/env ruby
2
2
 
3
- ENV['RAILS_ENV'] = 'production'
4
3
  require './config/environment.rb'
5
4
 
6
5
  require 'websocket-eventmachine-client'
7
6
  require 'json'
8
7
 
9
- notifiers = Hash[*ActiveRecord::Base.descendants.select { |cls| cls.respond_to?('seapig_dependency_version') }.map { |notifier| [notifier.name,notifier] }.flatten ]
10
8
 
11
- puts "Known notifiers:"
12
- notifiers.keys.each { |notifier| puts " "+notifier }
13
- puts
14
-
15
- $last_versions = {}
16
- $payloads = Queue.new
9
+ #ActiveRecord::Base.logger = Logger.new(STDERR)
17
10
 
18
11
  EM.run {
19
12
 
20
13
  socket = WebSocket::EventMachine::Client.connect(uri: ARGV[0])
21
-
14
+ connected = false
22
15
 
23
16
  on_database_change = Proc.new {
24
- payloads = Set.new
25
- payloads << $payloads.pop while not $payloads.empty?
26
- payloads.each { |notifier_name|
27
- version = notifiers[notifier_name].seapig_dependency_version #F handle wrong names
28
- p version
29
- if $last_versions[notifier_name] != version
30
- #socket.send(JSON.dump(action: 'object-update', id: notifier_name, version: version))
31
- socket.send(JSON.dump(action: 'object-patch', id: notifier_name, new_version: version, old_version: 0))
32
- $last_versions[notifier_name] = version
33
- end
17
+ next if not connected
18
+ SeapigDependency.where("current_version != reported_version").each { |seapig_dependency|
19
+ puts "Dependency version changed: %30s:%-10s"%[seapig_dependency.name,seapig_dependency.current_version]
20
+ socket.send(JSON.dump(action: 'object-patch', id: seapig_dependency.name, new_version: seapig_dependency.current_version, old_version: 0))
21
+ seapig_dependency.reported_version = seapig_dependency.current_version
22
+ seapig_dependency.save!
34
23
  }
35
24
  }
36
25
 
@@ -43,29 +32,26 @@ EM.run {
43
32
  connection.exec("LISTEN seapig_dependency_changed")
44
33
  loop {
45
34
  connection.wait_for_notify { |channel, pid, payloads|
46
- puts "Got notification: channel="+channel+", pid="+pid.inspect+", payload="+payloads.inspect
47
- payloads.split(",").each { |payload| $payloads << payload }
35
+ #puts "Got notification: channel="+channel+", pid="+pid.inspect+", payload="+payloads.inspect
48
36
  EM.schedule(on_database_change)
49
37
  }
50
38
  }
51
39
  }
52
40
  }
41
+ connected = true
53
42
  EM.schedule on_database_change
54
43
  }
55
44
 
56
-
45
+
57
46
  socket.onclose { |code, reason|
58
47
  EM.stop
59
48
  }
60
49
 
61
50
 
62
- EM.add_periodic_timer(60) {
63
- # socket.send(JSON.dump(action: 'object-update', id: 'Minute', version: Time.new.to_i/60))
64
- socket.send(JSON.dump(action: 'object-patch', id: 'Minute', new_version: Time.new.to_i/60, old_version: 0))
65
- }
66
-
67
- EM.add_periodic_timer(1) {
68
- socket.send(JSON.dump(action: 'object-patch', id: 'Second', new_version: Time.new.to_i, old_version: 0))
51
+ (ARGV[1] or "").split(',').each { |interval|
52
+ EM.add_periodic_timer(interval.to_i) {
53
+ socket.send(JSON.dump(action: 'object-patch', id: 'Seconds#'+interval, new_version: Time.new.to_i/interval.to_i, old_version: 0))
54
+ }
69
55
  }
70
56
  }
71
57
 
@@ -11,19 +11,22 @@ EM.run {
11
11
  SeapigServer.new(ARGV[0],name: 'session-saver').slave('web-session-data-*').onchange { |session_data|
12
12
  next if session_data.destroyed
13
13
  session_key = session_data.object_id
14
- p session_key
15
14
  session = SeapigRouterSession.find_by(key: session_key.split('-',4)[3])
16
- p session
15
+ if not session
16
+ puts "Ignoring unknown session: "+session_key
17
+ next
18
+ end
19
+ print "Saving session: "+session_key+" states: "
17
20
  max_state = session.seapig_router_session_states.order("state_id DESC").first
18
21
  max_state_id = (max_state and max_state.state_id or -1)
19
- p max_state, session_data['states'].map { |s| s['id'] }
20
22
  session_data['states'].each { |state|
21
- if state['id'] > max_state_id
22
- puts Time.new.to_s + " " + state.inspect
23
+ if state['id'] > max_state_id
24
+ print ' '+state['id'].inspect
23
25
  SeapigRouterSessionState.create!(seapig_router_session_id: session.id, state_id: state['id'], state: state)
24
26
  end
25
27
  }
26
- SeapigRouterSession.seapig_dependency_changed("SeapigRouterSessionState")
28
+ puts
29
+ SeapigDependency.bump("SeapigRouterSessionState#"+session.key)
27
30
  }
28
31
 
29
32
  }
@@ -0,0 +1,18 @@
1
+ class CreateSeapigVersions < ActiveRecord::Migration
2
+ def change
3
+ create_table :seapig_dependencies do |t|
4
+ t.text :name
5
+ t.bigint :current_version
6
+ t.bigint :reported_version
7
+
8
+ t.timestamps null: false
9
+ end
10
+
11
+ execute 'CREATE INDEX ON seapig_dependencies(name,current_version)'
12
+ execute 'CREATE INDEX ON seapig_dependencies((current_version != reported_version)) WHERE current_version != reported_version'
13
+ execute 'CREATE SEQUENCE seapig_dependency_version_seq OWNED BY seapig_dependencies.current_version'
14
+ end
15
+ end
16
+
17
+ # insert into seapig_dependencies (name,current_version,reported_version,created_at,updated_at) select 'reported' || generate_series, generate_series, generate_series, now(), now() from generate_series(1,1000000);
18
+ # insert into seapig_dependencies (name,current_version,reported_version,created_at,updated_at) select 'not-reported' || generate_series, generate_series, generate_series - 1 , now(), now() from generate_series(1,1000);
@@ -1,3 +1,3 @@
1
1
  module Seapig
2
- VERSION = "0.0.6"
2
+ VERSION = "0.0.7"
3
3
  end
data/lib/seapig-rails.rb CHANGED
@@ -1,5 +1,4 @@
1
1
  require "seapig/engine"
2
- require "seapig/acts_as_seapig_dependency.rb"
3
2
 
4
3
  module Seapig
5
4
  end
@@ -8,10 +8,9 @@ class SeapigRouterSessionSaved < Producer
8
8
  def self.produce(object_id)
9
9
  object_id =~ /web-session-saved-([^-]+)/
10
10
  session_key = $1
11
- version = {
12
- SeapigRouterSessionState: SeapigRouterSessionState.seapig_dependency_version
13
- }
11
+ version = SeapigDependency.versions('SeapigRouterSessionState#'+session_key)
14
12
  session = SeapigRouterSession.find_by(key: session_key)
13
+ return [false, version] if not session
15
14
  max_state = session.seapig_router_session_states.order("state_id DESC").first
16
15
  data = {
17
16
  max_state_id: (max_state and max_state.state_id or -1)
@@ -10,10 +10,10 @@ class SeapigRouterSessionStateProducer < Producer
10
10
  session_key = $1
11
11
  state_id = $2.to_i
12
12
  version = Time.new.to_f
13
- p session_key, object_id
14
13
  session = SeapigRouterSession.find_by(key: session_key)
14
+ return [false, SeapigDependency.versions('SeapigRouterSessionState#'+session_key)] if not session
15
15
  state = SeapigRouterSessionState.find_by(seapig_router_session_id: session.id, state_id: state_id)
16
- return [false, {SeapigRouterSessionState: SeapigRouterSessionState.seapig_dependency_version}] if not state
16
+ return [false, SeapigDependency.versions('SeapigRouterSessionState#'+session_key)] if not state
17
17
  data = state.state
18
18
  [data, version]
19
19
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: seapig-rails
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.6
4
+ version: 0.0.7
5
5
  platform: ruby
6
6
  authors:
7
7
  - yunta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-03-28 00:00:00.000000000 Z
11
+ date: 2016-06-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -78,8 +78,10 @@ files:
78
78
  - MIT-LICENSE
79
79
  - README.rdoc
80
80
  - Rakefile
81
+ - app/assets/javascripts/seapig/seapig-binding.js.coffee
81
82
  - app/assets/javascripts/seapig/seapig-client.js.coffee
82
83
  - app/assets/javascripts/seapig/seapig-router.js.coffee
84
+ - app/models/seapig_dependency.rb
83
85
  - app/models/seapig_router_session.rb
84
86
  - app/models/seapig_router_session_state.rb
85
87
  - bin/seapig-notifier
@@ -87,8 +89,8 @@ files:
87
89
  - config/routes.rb
88
90
  - db/migrate/20151221110834_create_seapig_router_sessions.rb
89
91
  - db/migrate/20151221111628_create_seapig_router_session_states.rb
92
+ - db/migrate/20151228202111_create_seapig_versions.rb
90
93
  - lib/seapig-rails.rb
91
- - lib/seapig/acts_as_seapig_dependency.rb
92
94
  - lib/seapig/engine.rb
93
95
  - lib/seapig/version.rb
94
96
  - lib/seapigs/seapig_router_saved_session.rb
@@ -1,34 +0,0 @@
1
- module SeapigDependency
2
-
3
- module ActsAsSeapigDependency
4
-
5
- extend ActiveSupport::Concern
6
-
7
-
8
- module ClassMethods
9
-
10
- def acts_as_seapig_dependency(options = {})
11
-
12
- self.instance_eval do
13
-
14
- def seapig_dependency_version
15
- self.find_by_sql('SELECT GREATEST(MAX(created_at), MAX(updated_at)) AS version FROM '+table_name).first.version.to_f
16
- end
17
-
18
- def seapig_dependency_changed(*tables)
19
- tables << self.name
20
- connection.instance_variable_get(:@connection).exec("NOTIFY seapig_dependency_changed,'"+tables.map { |table| table.kind_of?(Class) and table.name or table }.uniq.join(',')+"'")
21
- end
22
-
23
- end
24
-
25
- end
26
-
27
- end
28
-
29
- end
30
-
31
- end
32
-
33
-
34
- ActiveRecord::Base.send :include, SeapigDependency::ActsAsSeapigDependency