Remove SetValue/GetValue. Add debug console support for keeping track of streaming key values.
This commit is contained in:
34
api.py
34
api.py
@@ -30,7 +30,7 @@ def CreateChannel(google_user, client, args):
|
||||
token = channel.create_channel(
|
||||
client_id=str(client.key()),
|
||||
duration_minutes=config.CHANNEL_DURATION_SECONDS / 60)
|
||||
events = [x.ToEvent() for x in client.parent().GetStateEntries()]
|
||||
events = []
|
||||
if google_user:
|
||||
events.append({
|
||||
'event_type': 'login',
|
||||
@@ -57,37 +57,6 @@ def SendMessage(google_user, client, args):
|
||||
return {}
|
||||
|
||||
|
||||
@db.transactional()
|
||||
def SetValue(google_user, client, args):
|
||||
entry_key = args['key']
|
||||
entry_value = args['value']
|
||||
public = (args['public'] == 'true')
|
||||
|
||||
entries = (models.StateEntry.all()
|
||||
.ancestor(client.parent_key())
|
||||
.filter('entry_key =', entry_key)
|
||||
.fetch(1))
|
||||
if entries:
|
||||
entry = entries[0]
|
||||
entry.entry_value = entry_value
|
||||
entry.public = public
|
||||
else:
|
||||
entry = models.StateEntry(
|
||||
parent=client.parent_key(),
|
||||
entry_key=entry_key,
|
||||
entry_value=entry_value,
|
||||
public=public)
|
||||
|
||||
entry.put()
|
||||
event = entry.ToEvent()
|
||||
clients = (models.Client.all()
|
||||
.ancestor(client.parent_key()))
|
||||
for client in clients:
|
||||
client.SendEvent(event)
|
||||
|
||||
return {}
|
||||
|
||||
|
||||
def Subscribe(google_user, client, args):
|
||||
subject = models.Subject.FindOrCreate(args['subject'])
|
||||
messages = args.get('messages', 0)
|
||||
@@ -115,7 +84,6 @@ class APIWrapper(webapp2.RequestHandler):
|
||||
_COMMANDS = {
|
||||
'createChannel': CreateChannel,
|
||||
'sendMessage': SendMessage,
|
||||
'setValue': SetValue,
|
||||
'subscribe': Subscribe,
|
||||
'unsubscribe': Unsubscribe,
|
||||
}
|
||||
|
||||
@@ -24,7 +24,6 @@ import utils
|
||||
|
||||
# Profile
|
||||
# ↳ Client
|
||||
# ↳ StateEntry
|
||||
#
|
||||
# Subject
|
||||
# ↳ Message
|
||||
@@ -54,6 +53,7 @@ class Profile(db.Model):
|
||||
def MergeFrom(self, source_profile):
|
||||
# Merge from another profile into this one, using last_set time as the
|
||||
# arbiter.
|
||||
# TODO: this is totally broken
|
||||
my_states = {}
|
||||
for state_entry in self.GetStateEntries():
|
||||
my_states[state_entry.entry_key] = state_entry
|
||||
@@ -74,10 +74,6 @@ class Profile(db.Model):
|
||||
entry_value=state_entry.entry_value
|
||||
).put()
|
||||
|
||||
@db.transactional()
|
||||
def GetStateEntries(self):
|
||||
return StateEntry.all().ancestor(self)
|
||||
|
||||
|
||||
class Client(db.Model):
|
||||
# parent=Profile
|
||||
@@ -104,24 +100,6 @@ class Client(db.Model):
|
||||
channel.send_message(str(key), json.dumps(msg, default=utils.EncodeJSON))
|
||||
|
||||
|
||||
class StateEntry(db.Model):
|
||||
# parent=Profile
|
||||
|
||||
last_set = db.DateTimeProperty(required=True, auto_now=True)
|
||||
entry_key = db.StringProperty(required=True)
|
||||
entry_value = db.StringProperty()
|
||||
public = db.BooleanProperty(required=True, default=False)
|
||||
|
||||
def ToEvent(self):
|
||||
return {
|
||||
'event_type': 'state',
|
||||
'key': self.entry_key,
|
||||
'value': self.entry_value,
|
||||
'last_set': self.last_set,
|
||||
'public': self.public,
|
||||
}
|
||||
|
||||
|
||||
class Subject(db.Model):
|
||||
# key_name=name
|
||||
|
||||
|
||||
@@ -33,7 +33,6 @@ cosmopolite.Client = function(opt_callbacks, opt_urlPrefix, opt_namespace) {
|
||||
this.urlPrefix_ = opt_urlPrefix || '/cosmopolite';
|
||||
this.namespace_ = opt_namespace || 'cosmopolite';
|
||||
|
||||
this.stateCache_ = {};
|
||||
this.subscriptions_ = {};
|
||||
|
||||
var scriptUrls = [
|
||||
@@ -49,25 +48,8 @@ cosmopolite.Client = function(opt_callbacks, opt_urlPrefix, opt_namespace) {
|
||||
}, this);
|
||||
};
|
||||
|
||||
cosmopolite.Client.prototype.setValue = function(key, value, is_public) {
|
||||
this.sendRPC_('setValue', {
|
||||
'key': key,
|
||||
'value': value,
|
||||
'public': is_public,
|
||||
});
|
||||
// Provide immediate feedback without waiting for a round trip.
|
||||
// We'll also get a response from the server, so this should be eventually
|
||||
// consistent.
|
||||
if ('onStateChange' in this.callbacks_) {
|
||||
this.callbacks_['onStateChange'](key, value);
|
||||
}
|
||||
};
|
||||
|
||||
cosmopolite.Client.prototype.getValue = function(key) {
|
||||
return this.stateCache_[key];
|
||||
};
|
||||
|
||||
cosmopolite.Client.prototype.subscribe = function(subject, messages) {
|
||||
cosmopolite.Client.prototype.subscribe = function(subject, messages, keys) {
|
||||
keys = keys || [];
|
||||
if (subject in this.subscriptions_) {
|
||||
console.log('Not sending duplication subscription request for subject:', subject);
|
||||
return;
|
||||
@@ -78,6 +60,7 @@ cosmopolite.Client.prototype.subscribe = function(subject, messages) {
|
||||
this.sendRPC_('subscribe', {
|
||||
'subject': subject,
|
||||
'messages': messages,
|
||||
'keys': keys,
|
||||
});
|
||||
};
|
||||
|
||||
@@ -268,24 +251,6 @@ cosmopolite.Client.prototype.onSocketMessage_ = function(msg) {
|
||||
|
||||
cosmopolite.Client.prototype.onServerEvent_ = function(e) {
|
||||
switch (e.event_type) {
|
||||
case 'state':
|
||||
var key = e['key'];
|
||||
if (this.stateCache_[key] &&
|
||||
this.stateCache_[key]['value'] == e['value'] &&
|
||||
this.stateCache_[key]['last_set'] == e['last_set'] &&
|
||||
this.stateCache_[key]['public'] == e['public']) {
|
||||
// Duplicate event.
|
||||
break;
|
||||
}
|
||||
this.stateCache_[key] = {
|
||||
'value': e['value'],
|
||||
'last_set': e['last_set'],
|
||||
'public': e['public'],
|
||||
}
|
||||
if ('onStateChange' in this.callbacks_) {
|
||||
this.callbacks_['onStateChange'](key, this.stateCache_[key]);
|
||||
}
|
||||
break;
|
||||
case 'login':
|
||||
if ('onLogin' in this.callbacks_) {
|
||||
this.callbacks_['onLogin'](
|
||||
|
||||
@@ -10,25 +10,6 @@ a {
|
||||
<body>
|
||||
<div>Google user: <span id="google_user"></span></div>
|
||||
|
||||
<div>
|
||||
Key:
|
||||
<select id="keys"></select>
|
||||
<input type="button" id="set" value="Set">
|
||||
<input type="button" id="add" value="Add">
|
||||
</div>
|
||||
<div>
|
||||
Last set:
|
||||
<span id="last_set"></span>
|
||||
</div>
|
||||
<div>
|
||||
<input type="checkbox" id="public"> Public
|
||||
</div>
|
||||
<div>
|
||||
<textarea id="value" rows="10" cols="40"></textarea>
|
||||
</div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div>
|
||||
Subject: <input type="text" id="subject">
|
||||
<input type="button" id="subscribe" value="Subscribe">
|
||||
@@ -52,36 +33,23 @@ a {
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="keys"></div>
|
||||
|
||||
<hr>
|
||||
|
||||
<div id="messages"></div>
|
||||
|
||||
<script>
|
||||
var keys = document.getElementById('keys');
|
||||
var value = document.getElementById('value');
|
||||
var last_set = document.getElementById('last_set');
|
||||
var is_public = document.getElementById('public');
|
||||
|
||||
var subject = document.getElementById('subject');
|
||||
var subscriptions = document.getElementById('subscriptions');
|
||||
|
||||
var message = document.getElementById('message');
|
||||
var key = document.getElementById('key');
|
||||
|
||||
var keys = document.getElementById('keys');
|
||||
|
||||
var messages = document.getElementById('messages');
|
||||
|
||||
var selectKey = function(new_key) {
|
||||
keys.value = new_key;
|
||||
keys.dispatchEvent(new CustomEvent('change'));
|
||||
};
|
||||
|
||||
var addKey = function(new_key, index) {
|
||||
var option = document.createElement('option');
|
||||
option.text = new_key;
|
||||
keys.options.add(option, index);
|
||||
if (keys.options.length == 1) {
|
||||
selectKey(new_key);
|
||||
}
|
||||
};
|
||||
|
||||
var addMessage = function(message) {
|
||||
var messageDiv = document.createElement('div');
|
||||
messageDiv.appendChild(document.createTextNode(
|
||||
@@ -105,49 +73,36 @@ window.addEventListener('load', function() {
|
||||
googleUser.innerHTML =
|
||||
'<a href="' + login_url + '" target="_blank">(log in)</a>';
|
||||
},
|
||||
onStateChange: function(new_key, new_value) {
|
||||
for (var i = 0; i < keys.options.length; ++i) {
|
||||
if (keys.options[i].value == new_key) {
|
||||
return;
|
||||
};
|
||||
if (keys.options[i].value > new_key) {
|
||||
addKey(new_key, i);
|
||||
return;
|
||||
};
|
||||
};
|
||||
// Sorts at the end
|
||||
addKey(new_key, keys.options.length);
|
||||
},
|
||||
onMessage: function(message) {
|
||||
if (subscriptions.value != message['subject']) {
|
||||
return;
|
||||
}
|
||||
addMessage(message);
|
||||
if (message['key']) {
|
||||
var i;
|
||||
for (i = 0; i < keys.childNodes.length; i++) {
|
||||
var key = keys.childNodes[i];
|
||||
if (key.message['key'] == message['key']) {
|
||||
// Overwrite
|
||||
key.replaceChild(
|
||||
document.createTextNode(message['message']),
|
||||
key.childNodes[1]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (i == keys.childNodes.length) {
|
||||
var keyDiv = document.createElement('div');
|
||||
keyDiv.appendChild(document.createTextNode(message['key'] + ' = '));
|
||||
keyDiv.appendChild(document.createTextNode(message['message']));
|
||||
keyDiv.message = message;
|
||||
keys.appendChild(keyDiv);
|
||||
}
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
var debug = new cosmopolite.Client(callbacks);
|
||||
|
||||
document.getElementById('set').addEventListener('click', function() {
|
||||
debug.setValue(keys.value, value.value, is_public.checked);
|
||||
});
|
||||
|
||||
document.getElementById('add').addEventListener('click', function() {
|
||||
var new_key = prompt('New key name:');
|
||||
if (new_key === null) {
|
||||
return;
|
||||
}
|
||||
debug.setValue(new_key, '');
|
||||
selectKey(new_key);
|
||||
});
|
||||
|
||||
document.getElementById('keys').addEventListener('change', function() {
|
||||
var value_obj = debug.getValue(keys.value);
|
||||
value.value = value_obj.value;
|
||||
last_set.innerHTML = (new Date(value_obj.last_set * 1000)).toString();
|
||||
is_public.checked = value_obj['public'];
|
||||
});
|
||||
|
||||
document.getElementById('subscribe').addEventListener('click', function() {
|
||||
debug.subscribe(subject.value, -1);
|
||||
var option = document.createElement('option');
|
||||
|
||||
Reference in New Issue
Block a user