*** scoring schema migration

This commit is contained in:
Scott Comer 2014-02-21 22:21:31 -06:00
parent 65f529fb12
commit 4a9330523c
11 changed files with 242 additions and 11 deletions

View File

@ -115,4 +115,8 @@ music_sessions_plays.sql
plays_likes_counters.sql
add_upright_bass.sql
music_session_history_public.sql
track_claimed_recording.sql
track_claimed_recording.sql
scores_mod_users.sql
scores_mod_connections.sql
scores_create_schemas_and_extensions.sql
scores_create_tables.sql

View File

@ -0,0 +1,10 @@
-- integrating scores, modify schemas and extensions for postgis
CREATE SCHEMA tiger;
CREATE SCHEMA topology;
CREATE EXTENSION IF NOT EXISTS fuzzystrmatch WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS postgis WITH SCHEMA public;
CREATE EXTENSION IF NOT EXISTS postgis_tiger_geocoder WITH SCHEMA tiger;
CREATE EXTENSION IF NOT EXISTS plpgsql WITH SCHEMA pg_catalog;
CREATE EXTENSION IF NOT EXISTS postgis_topology WITH SCHEMA topology;

View File

@ -0,0 +1,145 @@
-- integrating scores, create geoip tables and jam shadows of those and scores
-----------------
-- geoipblocks --
-----------------
CREATE TABLE geoipblocks
(
beginip BIGINT NOT NULL,
endip BIGINT NOT NULL,
locid INTEGER NOT NULL
);
--------------
-- geoipisp --
--------------
CREATE TABLE geoipisp
(
beginip BIGINT NOT NULL,
endip BIGINT NOT NULL,
company CHARACTER VARYING(50) NOT NULL
);
CREATE INDEX geoipisp_company_ndx ON geoipisp (company);
--------------------
-- geoiplocations --
--------------------
CREATE TABLE geoiplocations
(
locid INTEGER PRIMARY KEY,
countrycode CHARACTER VARYING(2),
region CHARACTER VARYING(2),
city CHARACTER VARYING(255),
postalcode CHARACTER VARYING(8),
latitude DOUBLE PRECISION NOT NULL,
longitude DOUBLE PRECISION NOT NULL,
metrocode INTEGER,
areacode CHARACTER(3)
);
----------------
-- jamcompany --
----------------
CREATE TABLE jamcompany
(
coid SERIAL PRIMARY KEY,
company CHARACTER VARYING(50) NOT NULL
);
CREATE UNIQUE INDEX jamcompany_company_ndx ON jamcompany (company);
------------
-- jamisp --
------------
CREATE TABLE jamisp
(
beginip BIGINT NOT NULL,
endip BIGINT NOT NULL,
coid INTEGER NOT NULL
);
CREATE INDEX jamisp_coid_ndx ON jamisp (coid);
------------
-- scores --
------------
CREATE TABLE scores
(
alocidispid BIGINT NOT NULL,
anodeid CHARACTER VARYING(64) NOT NULL,
aaddr BIGINT NOT NULL,
blocidispid BIGINT NOT NULL,
bnodeid CHARACTER VARYING(64) NOT NULL,
baddr BIGINT NOT NULL,
score INTEGER NOT NULL,
scorer INTEGER NOT NULL,
score_dt TIMESTAMP NOT NULL DEFAULT current_timestamp
);
CREATE INDEX scores_alocidispid_blocidispid_score_dt_ndx ON scores (alocidispid, blocidispid, score_dt);
CREATE INDEX scores_blocidispid_alocidispid_score_dt_ndx ON scores (blocidispid, alocidispid, score_dt);
delete from GeoIPLocations;
insert into GeoIPLocations (locId, countryCode, region, city, postalCode, latitude, longitude, metroCode, areaCode) values
(17192,'US','TX','Austin','78749',30.2076,-97.8587,635,'512');
delete from GeoIPBlocks;
insert into GeoIPBlocks (beginIp, endIp, locId) values
(0,4294967295,17192);
delete from GeoIPISP;
insert into GeoIPISP values
(0,4294967295,'Intergalactic Boogie Corp');
DELETE FROM jamcompany;
ALTER SEQUENCE jamcompany_coid_seq RESTART WITH 1;
INSERT INTO jamcompany (company) SELECT DISTINCT company FROM geoipisp ORDER BY company;
DELETE FROM jamisp;
INSERT INTO jamisp (beginip, endip, coid) SELECT x.beginip, x.endip, y.coid FROM geoipisp x, jamcompany y WHERE x.company = y.company;
--ALTER TABLE geoiplocations DROP COLUMN geog;
ALTER TABLE geoiplocations ADD COLUMN geog geography(point, 4326);
UPDATE geoiplocations SET geog = ST_SetSRID(ST_MakePoint(longitude, latitude), 4326)::geography;
CREATE INDEX geoiplocations_geog_gix ON geoiplocations USING GIST (geog);
--ALTER TABLE geoipblocks DROP COLUMN geom;
ALTER TABLE geoipblocks ADD COLUMN geom geometry(polygon);
UPDATE geoipblocks SET geom = ST_MakeEnvelope(beginip, -1, endip, 1);
CREATE INDEX geoipblocks_geom_gix ON geoipblocks USING GIST (geom);
--ALTER TABLE jamisp DROP COLUMN geom;
ALTER TABLE jamisp ADD COLUMN geom geometry(polygon);
UPDATE jamisp SET geom = ST_MakeEnvelope(beginip, -1, endip, 1);
CREATE INDEX jamisp_geom_gix ON jamisp USING GIST (geom);
--DROP VIEW current_scores;
CREATE VIEW current_scores AS SELECT * FROM scores s WHERE score_dt = (SELECT max(score_dt) FROM scores s0 WHERE s0.alocidispid = s.alocidispid AND s0.blocidispid = s.blocidispid);
--DROP FUNCTION get_work (mylocidispid BIGINT);
CREATE FUNCTION get_work (mylocidispid BIGINT)
RETURNS TABLE (client_id VARCHAR(64))
LANGUAGE plpgsql
ROWS 5
VOLATILE
AS $BODY$
BEGIN
CREATE TEMPORARY TABLE foo (locidispid BIGINT, locid INT);
INSERT INTO foo SELECT DISTINCT locidispid, locidispid/1000000 FROM connections;
DELETE FROM foo WHERE locidispid IN (SELECT DISTINCT blocidispid FROM current_scores WHERE alocidispid = mylocidispid AND (current_timestamp - score_dt) < interval '24 hours');
DELETE FROM foo WHERE locid NOT IN (SELECT locid FROM geoiplocations WHERE geog && st_buffer((SELECT geog from geoiplocations WHERE locid = mylocidispid/1000000), 806000));
CREATE TEMPORARY TABLE bar (client_id VARCHAR(64), locidispid BIGINT, r DOUBLE PRECISION);
INSERT INTO bar SELECT l.client_id, l.locidispid, random() FROM connections l, foo f WHERE l.locidispid = f.locidispid;
DROP TABLE foo;
DELETE FROM bar b WHERE r != (SELECT max(r) FROM bar b0 WHERE b0.locidispid = b.locidispid);
RETURN QUERY SELECT b.client_id FROM bar b ORDER BY r LIMIT 5;
DROP TABLE bar;
RETURN;
END $BODY$;

View File

@ -0,0 +1,28 @@
-- integrating scores, modify connections object to:
-- drop ip_address (text field)
-- add addr, locidispid, latitude, longitude, countrycode, region, city
-- note, this will force logout of everyone so that the new not null columns will be populated.
DELETE FROM connections;
-- ALTER TABLE connections DROP COLUMN ip_address;
ALTER TABLE connections ADD COLUMN addr BIGINT;
ALTER TABLE connections ALTER COLUMN addr SET NOT NULL;
ALTER TABLE connections ADD COLUMN locidispid INT;
ALTER TABLE connections ALTER COLUMN locidispid SET NOT NULL;
ALTER TABLE connections ADD COLUMN latitude DOUBLE PRECISION;
ALTER TABLE connections ALTER COLUMN latitude SET NOT NULL;
ALTER TABLE connections ADD COLUMN longitude DOUBLE PRECISION;
ALTER TABLE connections ALTER COLUMN longitude SET NOT NULL;
ALTER TABLE connections ADD COLUMN countrycode CHARACTER VARYING(2);
ALTER TABLE connections ADD COLUMN region CHARACTER VARYING(2);
ALTER TABLE connections ADD COLUMN city CHARACTER VARYING(255);
CREATE INDEX connections_locidispid_ndx ON connections (locidispid);

View File

@ -0,0 +1,15 @@
-- integrating scores, modify users table to:
-- todo state should be region, country should be countrycode, lat, lng should be latitude, longitude
-- add addr, locidispid
-- these fields will be updated on login to reflect the last connection details
ALTER TABLE users ADD COLUMN addr BIGINT;
ALTER TABLE users ADD COLUMN locidispid INTEGER;
ALTER TABLE users ALTER COLUMN addr SET DEFAULT 0;
ALTER TABLE users ALTER COLUMN locidispid SET DEFAULT 0;
UPDATE users SET addr = 0, locidispid = 0;
ALTER TABLE users ALTER COLUMN addr SET NOT NULL;
ALTER TABLE users ALTER COLUMN locidispid SET NOT NULL;

View File

@ -5,7 +5,7 @@ module JamRuby
# for 'SQL convenience', this is a obvious place we can go away from a database
# as an optimization if we find it's too much db traffic created'
# At a minimum, though, we could make connections an UNLOGGED table because if the database crashes,
# all clients should reconnect and restablish their connection anyway
# all clients should reconnect and re-establish their connection anyway
#
# All methods in here could also be refactored as stored procedures, if we stick with a database.
# This may make sense in the short term if we are still managing connections in the database, but
@ -43,8 +43,8 @@ module JamRuby
music_session.before_destroy if music_session
end
# reclaim the existing connection,
def reconnect(conn, reconnect_music_session_id)
# reclaim the existing connection, if ip_address is not nil then perhaps a new address as well
def reconnect(conn, reconnect_music_session_id, ip_address)
music_session_id = nil
reconnected = false
@ -55,6 +55,9 @@ module JamRuby
music_session_id_expression = "(CASE WHEN music_session_id='#{reconnect_music_session_id}' THEN music_session_id ELSE NULL END)"
end
if ip_address
# todo turn ip_address string into a number, then fetch the locid and ispid and the other stuff...
end
sql =<<SQL
UPDATE connections SET (aasm_state, updated_at, music_session_id) = ('#{Connection::CONNECT_STATE.to_s}', NOW(), #{music_session_id_expression})
@ -164,11 +167,21 @@ SQL
count = 0
ConnectionManager.active_record_transaction do |connection_manager|
conn = connection_manager.pg_conn
# todo turn ip_address string into a number, then fetch the locid and ispid and the other stuff...
addr = 0
locidispid = 0
latitude = 0.0
longitude = 0.0
countrycode = 'US'
region = 'TX'
city = 'Austin'
lock_connections(conn)
conn.exec("INSERT INTO connections (user_id, client_id, ip_address, aasm_state) VALUES ($1, $2, $3, $4)",
[user_id, client_id, ip_address, Connection::CONNECT_STATE.to_s]).clear
conn.exec("INSERT INTO connections (user_id, client_id, addr, locidispid, latitude, longitude, countrycode, region, city, aasm_state) VALUES ($1, $2, $3, $4, $5, $6, $7, $8, $9, $10)",
[user_id, client_id, addr, locidispid, latitude, longitude, countrycode, region, city, Connection::CONNECT_STATE.to_s]).clear
# we just created a new connection-if this is the first time the user has shown up, we need to send out a message to his friends
conn.exec("SELECT count(user_id) FROM connections WHERE user_id = $1", [user_id]) do |result|

View File

@ -87,7 +87,15 @@ FactoryGirl.define do
factory :connection, :class => JamRuby::Connection do
sequence(:client_id) { |n| "Client#{n}" }
ip_address "1.1.1.1"
as_musician true
addr 0
locidispid 0
latitude 0.0
longitude 0.0
countrycode 'US'
region 'TX'
city 'Austin'
end
factory :invitation, :class => JamRuby::Invitation do

View File

@ -32,7 +32,7 @@ class ApiBandsController < ApiController
def validate
@band = Band.build_band(current_user, params)
@band.valid?
puts ">>>>>>>>>>>>>>>>> #{@band.errors.inspect}" if @band.errors.any?
respond_with_model(@band)
end

View File

@ -70,9 +70,16 @@ FactoryGirl.define do
factory :connection, :class => JamRuby::Connection do
sequence(:client_id) { |n| "client_id#{n}"}
ip_address "1.1.1.1"
as_musician true
sequence(:client_id) { |n| "client_id#{n}"}
addr 0
locidispid 0
latitude 0.0
longitude 0.0
countrycode 'US'
region 'TX'
city 'Austin'
end
factory :friendship, :class => JamRuby::Friendship do

View File

@ -47,6 +47,7 @@ describe "Bands", :js => true, :type => :feature, :capybara_feature => true do
first('#band-genres input[type="checkbox"]').trigger(:click)
end
sleep 1 # work around race condition
find('#btn-band-setup-next').trigger(:click)
find('h2', text: 'Step 2: Add Band Members')

View File

@ -463,6 +463,7 @@ module JamWebsockets
end
client.client_id = client_id
remote_ip = extract_ip(client)
if !user.nil?
@log.debug "user #{user} logged in with client_id #{client_id}"
@ -475,7 +476,7 @@ module JamWebsockets
music_session_upon_reentry = connection.music_session
ConnectionManager.active_record_transaction do |connection_manager|
music_session_id, reconnected = connection_manager.reconnect(connection, reconnect_music_session_id)
music_session_id, reconnected = connection_manager.reconnect(connection, reconnect_music_session_id, remote_ip)
context = @client_lookup[client_id]
if music_session_id.nil?
# if this is a reclaim of a connection, but music_session_id comes back null, then we need to check if this connection was IN a music session before.
@ -494,7 +495,6 @@ module JamWebsockets
end
# respond with LOGIN_ACK to let client know it was successful
remote_ip = extract_ip(client)
@semaphore.synchronize do
# remove from pending_queue
@ -545,7 +545,7 @@ module JamWebsockets
connection.touch
ConnectionManager.active_record_transaction do |connection_manager|
connection_manager.reconnect(connection, connection.music_session_id)
connection_manager.reconnect(connection, connection.music_session_id, nil)
end if connection.stale?
end