seapig-rails 0.0.1 → 0.0.2

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: 25b28f9d7975a6bfd32062f20bc310c01d79735e
4
- data.tar.gz: 186a43d3f1e36b1b8b1244d6524b344388d34e74
3
+ metadata.gz: 02ffc579c05bd9348fb6951b13c49e2dd59fd9de
4
+ data.tar.gz: 4085bb327476405fdc3f9d219fffa8c5fbece221
5
5
  SHA512:
6
- metadata.gz: 31bd90e20f73825d39bcafd121eaf070a0f35229bfd2d574ca63ae96ed1b00d7b5e33343622acae53dd5c28c9ed02cad3e7d6895ac720cdc660f5dab254d9d7d
7
- data.tar.gz: ce55ecb9cfe3acfcb52b8d24992b2ed4b037f15700d6da06590e602b1352754a12ffaf94f9d249b6747c60b14b93de8d8734cffeada736ad30e5abf58363ac57
6
+ metadata.gz: 891935bfbb159d2c385790a4bcb04720c3e0d71ac644c09620619a0dcdef82254c6b0fbf68ca5c42590b3a326e4fd7e44c98dfbf3c28444be1afe6a1c3fa7375
7
+ data.tar.gz: 3df6423bed314b75e7c549a095955ffe511dfbee16d5f7da781c74b219849ee83088dc2e5a5790cafca44c8172392524d99a7b978afb2f11fc5256e30a353664
@@ -30,6 +30,9 @@ class @SeapigServer
30
30
  @socket.send(JSON.stringify(action: 'client-options-set', options: @options))
31
31
  for object_id, object of @slave_objects
32
32
  @socket.send(JSON.stringify(action: 'object-consumer-register', id: object_id, latest_known_version: object.version))
33
+ for object_id, object of @master_objects
34
+ @socket.send(JSON.stringify(action: 'object-producer-register', pattern: object_id))
35
+ object.upload(0,{})
33
36
 
34
37
  @socket.onmessage = (event) =>
35
38
  #console.log('Seapig message received', event)
@@ -37,45 +40,71 @@ class @SeapigServer
37
40
  switch data.action
38
41
  when 'object-update'
39
42
  @slave_objects[data.id].patch(data) if @slave_objects[data.id]
43
+ when 'object-produce'
44
+ @master_objects[data.id].upload(0,{}) if @master_objects[data.id]
40
45
  else
41
46
  console.log('Seapig received a stupid message', data)
42
47
 
43
48
 
44
49
  slave: (object_id) ->
45
- @socket.send(JSON.stringify(action: 'object-consumer-register', id: object_id, latest_known_version: null)) if @connected
46
- @slave_objects[object_id] = new SeapigObject(object_id)
50
+ @socket.send(JSON.stringify(action: 'object-consumer-register', id: object_id, latest_known_version: 0)) if @connected
51
+ @slave_objects[object_id] = new SeapigObject(@,object_id)
47
52
 
48
53
 
49
- unlink: (object_id) ->
50
- delete @slave_objects[object_id]
51
- @socket.send(JSON.stringify(action: 'unlink', id: object_id)) if @connected
54
+ master: (object_id) ->
55
+ @socket.send(JSON.stringify(action: 'object-producer-register', pattern: object_id)) if @connected
56
+ @master_objects[object_id] = new SeapigObject(@,object_id)
52
57
 
53
58
 
59
+ unlink: (object_id)->
60
+ if @slave_objects[object_id]?
61
+ delete @slave_objects[object_id]
62
+ @socket.send(JSON.stringify(action: 'object-consumer-unregister', id: object_id)) if @connected
63
+ if @master_objects[object_id]?
64
+ delete @master_objects[object_id]
65
+ @socket.send(JSON.stringify(action: 'object-producer-unregister', id: object_id)) if @connected
66
+
54
67
 
55
68
  class SeapigObject
56
69
 
57
70
 
58
- constructor: (id) ->
71
+ constructor: (server,id) ->
72
+ @server = server
59
73
  @id = id
60
74
  @valid = false
61
- @version = null
75
+ @version = 0
62
76
  @object = {}
63
77
  @shadow = {}
64
78
  @onchange = null
65
79
 
66
80
 
67
81
  patch: (data) ->
68
- if not data.old_version?
82
+ if data.old_version == 0
69
83
  delete @object[key] for key, value of @object
70
84
  else if not _.isEqual(@version, data.old_version)
71
- console.log("Seapig lost some updates, this shouldn't ever happen", @version, data.old_version)
85
+ console.log("Seapig lost some updates, this shouldn't ever happen. object:",@id," version:", @version, " old_version:", data.old_version)
72
86
  jsonpatch.apply(@object, data.patch)
73
87
  @version = data.new_version
74
88
  @valid = true
75
89
  @onchange() if @onchange?
76
90
 
77
91
  changed: () ->
92
+ old_version = @version
78
93
  @version += 1
79
- patch = jsonpatch.compare(@shadow, @object)
80
- console.log(patch)
94
+ @upload(old_version, @shadow)
81
95
  @shadow = JSON.parse(JSON.stringify(@object))
96
+
97
+
98
+ upload: (old_version, old_object)->
99
+ message = {
100
+ id: @id
101
+ action: 'object-patch'
102
+ old_version: old_version
103
+ new_version: @version
104
+ patch: jsonpatch.compare(old_object, @object)
105
+ }
106
+ @server.socket.send(JSON.stringify(message)) if @server.connected
107
+
108
+
109
+ unlink: () ->
110
+ @server.unlink(@id)
@@ -0,0 +1,104 @@
1
+ class @SeapigRouter
2
+
3
+
4
+ constructor: (seapig_server, session_id, initial_state, debug = false)->
5
+ @seapig_server = seapig_server
6
+ @session_id = session_id
7
+ @debug = debug
8
+
9
+ @state = _.extend({session_id: @session_id, id: 0}, initial_state)
10
+
11
+ @session_data = @seapig_server.master('web-session-data-'+@session_id)
12
+ @session_data.object.states = [ @state ]
13
+ @session_data.sequence = 1
14
+ @session_data.changed()
15
+
16
+ @session_data_saved = @seapig_server.slave('web-session-saved-'+@session_id)
17
+ @session_data_saved.onchange = ()=>
18
+ while @session_data.object.states[0]? and @session_data.object.states[0].id < @session_data_saved.object.max_state_id
19
+ @session_data.object.states.shift()
20
+ @replacing_state = true
21
+ window.history.replaceState(@state,null,@current_url())
22
+ @replacing_state = false
23
+
24
+
25
+ @replacing_state = false
26
+ @state_valid = false
27
+
28
+ $(document).on('click','a', (event) =>
29
+ console.log('ROUTER: A-element clicked, changing location to:', event.target.href) if @debug
30
+ return true if not event.target.href[0] == '?'
31
+ window.history.pushState(null,null,event.target.href)
32
+ @location_changed()
33
+ false
34
+ )
35
+
36
+ window.onpopstate = (data) =>
37
+ @state = data.state
38
+ @state_changed()
39
+
40
+
41
+
42
+ location_changed: () ->
43
+ return if @replacing_state
44
+ console.log('ROUTER: Location changed to: pathname:', window.location.pathname, ' search:', window.location.search) if @debug
45
+
46
+ spl = window.location.pathname.split('/')
47
+ if spl[1] == 'a'
48
+ path_session_id = spl[2]
49
+ path_state_id = spl[3]
50
+ else
51
+ path_session_id = @session_id
52
+ path_state_id = 0
53
+
54
+ overlay = {}
55
+ if window.location.search.length > 0
56
+ for pair in window.location.search.split('?')[1].split('&')
57
+ spl = pair.split('=',2)
58
+ overlay[spl[0]] = spl[1]
59
+
60
+ if path_session_id == @session_id
61
+ @state_change(overlay)
62
+ else
63
+ if @remote_state?
64
+ @state_change_to_remote(overlay)
65
+ else
66
+ @state_valid = false
67
+ @remote_state = @seapig_server.slave('web-session-state-'+path_session_id+':'+path_state_id)
68
+ @remote_state.onchange = ()=> @state_change_to_remote(overlay)
69
+
70
+
71
+ state_change_to_remote: (overlay) ->
72
+ @state = _.clone(@remote_state.object)
73
+ if _.size(overlay) > 0
74
+ @state_change(overlay)
75
+ else
76
+ @state_valid = true
77
+ @state_changed()
78
+
79
+
80
+ state_change: (overlay) ->
81
+ @state = _.extend(_.clone(@state), overlay)
82
+ @statefilter(@state) if @statefilter?
83
+ @state.session_id = @session_id
84
+ @state.id = @session_data.sequence++
85
+ @session_data.object.states.push(@state)
86
+ @session_data.changed()
87
+ if @remote_state?
88
+ @remote_state.unlink()
89
+ @remote_state = null
90
+ @state_valid = true
91
+ @state_changed()
92
+
93
+
94
+ current_url: ()->
95
+ '/a/'+@state.session_id+'/'+@state.id+(if (@session_data_saved.object.max_state_id >= @state.id or @state.session_id != @session_id) then '' else '#NOT-SHAREABLE')
96
+
97
+ state_changed: () ->
98
+
99
+ console.log("ROUTER: State changed to: state:", @state, ' url:', @current_url()) if @debug
100
+ @replacing_state = true
101
+ window.history.replaceState(@state,null,@current_url())
102
+ @replacing_state = false
103
+
104
+ @onstatechange(@state) if @onstatechange?
@@ -0,0 +1,19 @@
1
+ class SeapigRouterSession < ActiveRecord::Base
2
+
3
+ has_many :seapig_router_session_states
4
+
5
+ acts_as_seapig_dependency
6
+
7
+
8
+ def self.generate
9
+ session = SeapigRouterSession.new
10
+ begin
11
+ session.key = (('a'..'z').to_a + ('A'..'Z').to_a + (0..9).to_a).shuffle[0..10].join('')
12
+ session.save!
13
+ rescue ActiveRecord::RecordNotUnique
14
+ retry
15
+ end
16
+ session
17
+ end
18
+
19
+ end
@@ -0,0 +1,7 @@
1
+ class SeapigRouterSessionState < ActiveRecord::Base
2
+
3
+ belongs_to :seapig_router_session
4
+
5
+ acts_as_seapig_dependency
6
+
7
+ end
@@ -0,0 +1,30 @@
1
+ #!/bin/env ruby
2
+
3
+ require './config/environment.rb'
4
+
5
+ require 'seapig-client'
6
+
7
+
8
+
9
+ EM.run {
10
+
11
+ SeapigServer.new(ARGV[0],name: 'session-saver').slave('web-session-data-*').onchange { |sessions|
12
+ sessions.each_pair { |session_key, session_data|
13
+ p session_key
14
+ session = SeapigRouterSession.find_by(key: session_key.split('-',4)[3])
15
+ max_state = session.seapig_router_session_states.order("state_id DESC").first
16
+ max_state_id = (max_state and max_state.state_id or -1)
17
+ session_data['states'].each { |state|
18
+ if state['id'] > max_state_id
19
+ puts Time.new.to_s + " " + state.inspect
20
+ SeapigRouterSessionState.create!(seapig_router_session_id: session.id, state_id: state['id'], state: state)
21
+ end
22
+ }
23
+ }
24
+ SeapigRouterSession.seapig_dependency_changed("SeapigRouterSessionState")
25
+ }
26
+
27
+ }
28
+
29
+
30
+
@@ -0,0 +1,9 @@
1
+ class CreateSeapigRouterSessions < ActiveRecord::Migration
2
+ def change
3
+ create_table :seapig_router_sessions do |t|
4
+ t.text :key
5
+ t.timestamps null: false
6
+ end
7
+ add_index :seapig_router_sessions, :key, unique: true
8
+ end
9
+ end
@@ -0,0 +1,13 @@
1
+ class CreateSeapigRouterSessionStates < ActiveRecord::Migration
2
+ def change
3
+ create_table :seapig_router_session_states do |t|
4
+ t.integer :seapig_router_session_id
5
+ t.integer :state_id
6
+ t.jsonb :state
7
+
8
+ t.timestamps null: false
9
+ end
10
+ add_index :seapig_router_session_states, [:seapig_router_session_id,:state_id], unique: true, name: "seapig_router_session_states_index_1"
11
+
12
+ end
13
+ end
@@ -1,3 +1,3 @@
1
1
  module Seapig
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -0,0 +1,22 @@
1
+ require './config/environment.rb'
2
+
3
+ class SeapigRouterSessionSaved < Producer
4
+
5
+ @patterns = [ 'web-session-saved-*' ]
6
+
7
+
8
+ def self.produce(object_id)
9
+ object_id =~ /web-session-saved-([^-]+)/
10
+ session_key = $1
11
+ version = {
12
+ SeapigRouterSessionState: SeapigRouterSessionState.seapig_dependency_version
13
+ }
14
+ session = SeapigRouterSession.find_by(key: session_key)
15
+ max_state = session.seapig_router_session_states.order("state_id DESC").first
16
+ data = {
17
+ max_state_id: (max_state and max_state.state_id or -1)
18
+ }
19
+ [data, version]
20
+ end
21
+
22
+ end
@@ -0,0 +1,20 @@
1
+ require './config/environment.rb'
2
+
3
+ class SeapigRouterSessionStateProducer < Producer
4
+
5
+ @patterns = [ 'web-session-state-*' ]
6
+
7
+
8
+ def self.produce(object_id)
9
+ object_id =~ /web-session-state-([^-]+)\:(\d+)/
10
+ session_key = $1
11
+ state_id = $2.to_i
12
+ version = Time.new.to_f
13
+ p session_key, object_id
14
+ session = SeapigRouterSession.find_by(key: session_key)
15
+ data = SeapigRouterSessionState.find_by(seapig_router_session_id: session.id, state_id: state_id).state
16
+ p data
17
+ [data, version]
18
+ end
19
+
20
+ end
@@ -3,7 +3,7 @@ require File.expand_path('../boot', __FILE__)
3
3
  require 'rails/all'
4
4
 
5
5
  Bundler.require(*Rails.groups)
6
- require "seapig-rails"
6
+ require "seapig"
7
7
 
8
8
  module Dummy
9
9
  class Application < Rails::Application
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.1
4
+ version: 0.0.2
5
5
  platform: ruby
6
6
  authors:
7
7
  - yunta
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-02-21 00:00:00.000000000 Z
11
+ date: 2016-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -71,19 +71,28 @@ email:
71
71
  - maciej.blomberg@mikoton.com
72
72
  executables:
73
73
  - seapig-notifier
74
+ - seapig-session-saver
74
75
  extensions: []
75
76
  extra_rdoc_files: []
76
77
  files:
77
78
  - MIT-LICENSE
78
79
  - README.rdoc
79
80
  - Rakefile
80
- - app/assets/javascripts/seapig/seapig.js.coffee
81
+ - app/assets/javascripts/seapig/seapig-client.js.coffee
82
+ - app/assets/javascripts/seapig/seapig-router.js.coffee
83
+ - app/models/seapig_router_session.rb
84
+ - app/models/seapig_router_session_state.rb
81
85
  - bin/seapig-notifier
86
+ - bin/seapig-session-saver
82
87
  - config/routes.rb
88
+ - db/migrate/20151221110834_create_seapig_router_sessions.rb
89
+ - db/migrate/20151221111628_create_seapig_router_session_states.rb
83
90
  - lib/seapig-rails.rb
84
91
  - lib/seapig/acts_as_seapig_dependency.rb
85
92
  - lib/seapig/engine.rb
86
93
  - lib/seapig/version.rb
94
+ - lib/seapigs/seapig_router_saved_session.rb
95
+ - lib/seapigs/seapig_router_session_state.rb
87
96
  - lib/tasks/seapig_tasks.rake
88
97
  - test/dummy/README.rdoc
89
98
  - test/dummy/Rakefile