Skip to content
This repository has been archived by the owner on Jan 31, 2018. It is now read-only.

[bug 1103141] Add experiment_version to HB db and api #391

Merged
merged 1 commit into from
Nov 21, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
93 changes: 52 additions & 41 deletions docs/hb_api.rst
Expand Up @@ -38,47 +38,53 @@ These fields are required and have no defaults. If you do not provide
them, then you'll get back an HTTP 400 with a message stating you
missed a required field.

+----------------+-------+--------------------------------------------------------+
|field |type |notes |
+================+=======+========================================================+
|person_id |string |max length: 50; Id representating a person's browser. |
| | |Global across surveys and flows. |
+----------------+-------+--------------------------------------------------------+
|survey_id |string |This is the survey name as it is set up in Input. This |
| | |is the only field that has a foreign key to another |
| | |table in Input and must be set up before running a |
| | |survey. |
| | | |
+----------------+-------+--------------------------------------------------------+
|flow_id |string |max length: 50; Id uniquely identifying a flow attempt |
| | |for this survey. |
| | | |
| | | |
| | | |
+----------------+-------+--------------------------------------------------------+
|question_id |string |max length: 50; Id uniquely identifying a question for |
| | |this survey. This allows us to tweak the question text |
| | |for a survey without launching a new survey. |
| | | |
| | | |
+----------------+-------+--------------------------------------------------------+
|response_version|integer|This is the version of the packet specification. Any |
| | |time the values of the packet or the calculation of the |
| | |values for the packet change, we should increase the |
| | |``response_version``. This allows us to distinguish |
| | |between different packet builds when doing analysis. |
+----------------+-------+--------------------------------------------------------+
|updated_ts |integer|Milliseconds since the epoch for when this packet was |
| | |created. |
| | | |
| | |Every time you update data for a flow attempt, it should|
| | |include a new and more recent ``updated_ts``. |
+----------------+-------+--------------------------------------------------------+
|question_text |string |Max length: None; Default: ``""``; The actual question |
| | |asked. This can be localized. |
+----------------+-------+--------------------------------------------------------+
|variation_id |string |Max length: 50; Default: ``""`` |
+----------------+-------+--------------------------------------------------------+
+------------------+-------+--------------------------------------------------------+
|field |type |notes |
+==================+=======+========================================================+
|response_version |integer|This is the version of the packet specification. Any |
| | |time the values of the packet or the calculation of the |
| | |values for the packet change, we should increase the |
| | |``response_version``. This allows us to distinguish |
| | |between different packet builds when doing analysis. |
+------------------+-------+--------------------------------------------------------+
|experiment_version|string |Max length: 50; The version of the experiment addon. |
| | | |
| | | |
| | | |
| | | |
+------------------+-------+--------------------------------------------------------+
|person_id |string |Max length: 50; Id representating a person's browser. |
| | |Global across surveys and flows. |
+------------------+-------+--------------------------------------------------------+
|survey_id |string |This is the survey name as it is set up in Input. This |
| | |is the only field that has a foreign key to another |
| | |table in Input and must be set up before running a |
| | |survey. |
| | | |
+------------------+-------+--------------------------------------------------------+
|flow_id |string |Max length: 50; Id uniquely identifying a flow attempt |
| | |for this survey. |
| | | |
| | | |
| | | |
+------------------+-------+--------------------------------------------------------+
|question_id |string |Max length: 50; Id uniquely identifying a question for |
| | |this survey. This allows us to tweak the question text |
| | |for a survey without launching a new survey. |
| | | |
| | | |
+------------------+-------+--------------------------------------------------------+
|updated_ts |integer|Milliseconds since the epoch for when this packet was |
| | |created. |
| | | |
| | |Every time you update data for a flow attempt, it should|
| | |include a new and more recent ``updated_ts``. |
+------------------+-------+--------------------------------------------------------+
|question_text |string |Max length: None; Default: ``""``; The actual question |
| | |asked. This can be localized. |
+------------------+-------+--------------------------------------------------------+
|variation_id |string |Max length: 100; Default: ``""`` |
+------------------+-------+--------------------------------------------------------+


Optional fields
Expand Down Expand Up @@ -159,6 +165,7 @@ Example curl::
"person_id": "c1dd81f2-6ece-11e4-8a01-843a4bc832e4",
"survey_id": "lunch",
"flow_id": "20141117_attempt1",
"experiment_version": "1",
"response_version": 1,
"question_id": "howwaslunch",
"question_text": "how was lunch?",
Expand Down Expand Up @@ -200,6 +207,7 @@ Example curl::
"survey_id": "nonexistent",
"flow_id": "20141114_attempt2",
"response_version": 1,
"experiment_version": "1",
"question_id": "howwaslunch",
"updated_ts": 1416011156000,
"is_test": true
Expand Down Expand Up @@ -257,6 +265,7 @@ Anything less than this will kick up "required" type errors.
"person_id": "c1dd81f2-6ece-11e4-8a01-843a4bc832e4",
"survey_id": "lunch",
"flow_id": "20141117_attempt1",
"experiment_version": "1",
"response_version": 1,
"question_id": "howwaslunch",
"question_text": "how was lunch?",
Expand Down Expand Up @@ -284,6 +293,7 @@ Began:
"person_id": "c1dd81f2-6ece-11e4-8a01-843a4bc832e4",
"survey_id": "lunch",
"flow_id": "20141117_attempt5",
"experiment_version": "1",
"response_version": 1,
"question_id": "howwaslunch",
"updated_ts": 1416011156000,
Expand Down Expand Up @@ -319,6 +329,7 @@ Voted, but not engaged, yet::
"person_id": "c1dd81f2-6ece-11e4-8a01-843a4bc832e4",
"survey_id": "lunch",
"flow_id": "20141117_attempt7",
"experiment_version": "1",
"response_version": 1,
"question_id": "howwaslunch",
"updated_ts": 1416011180000,
Expand Down
@@ -0,0 +1,62 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):
# Adding field 'Answer.experiment_version'
db.add_column(u'heartbeat_answer', 'experiment_version',
self.gf('django.db.models.fields.CharField')(default='', max_length=50),
keep_default=False)


def backwards(self, orm):
# Deleting field 'Answer.experiment_version'
db.delete_column(u'heartbeat_answer', 'experiment_version')


models = {
u'heartbeat.answer': {
'Meta': {'object_name': 'Answer'},
'addons': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'build_id': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'channel': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'experiment_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'extra': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'flow_began_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_engaged_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'flow_offered_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_voted_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_test': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'locale': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'max_score': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'partner_id': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'person_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'platform': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'profile_age': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
'profile_usage': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'question_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'question_text': ('django.db.models.fields.TextField', [], {}),
'response_version': ('django.db.models.fields.IntegerField', [], {}),
'score': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'survey_id': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['heartbeat.Survey']", 'to_field': "'name'", 'db_column': "'survey_id'"}),
'updated_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'variation_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'version': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'})
},
u'heartbeat.survey': {
'Meta': {'object_name': 'Survey'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
}
}

complete_apps = ['heartbeat']
@@ -0,0 +1,60 @@
# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import SchemaMigration
from django.db import models


class Migration(SchemaMigration):

def forwards(self, orm):

# Changing field 'Answer.variation_id'
db.alter_column(u'heartbeat_answer', 'variation_id', self.gf('django.db.models.fields.CharField')(max_length=100))

def backwards(self, orm):

# Changing field 'Answer.variation_id'
db.alter_column(u'heartbeat_answer', 'variation_id', self.gf('django.db.models.fields.CharField')(max_length=50))

models = {
u'heartbeat.answer': {
'Meta': {'object_name': 'Answer'},
'addons': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'build_id': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'channel': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'experiment_version': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'extra': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'flow_began_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_engaged_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'flow_offered_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'flow_voted_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_test': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'locale': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'max_score': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'partner_id': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'person_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'platform': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'}),
'profile_age': ('django.db.models.fields.BigIntegerField', [], {'null': 'True', 'blank': 'True'}),
'profile_usage': ('fjord.base.models.JSONObjectField', [], {'default': '{}', 'blank': 'True'}),
'question_id': ('django.db.models.fields.CharField', [], {'max_length': '50'}),
'question_text': ('django.db.models.fields.TextField', [], {}),
'response_version': ('django.db.models.fields.IntegerField', [], {}),
'score': ('django.db.models.fields.FloatField', [], {'null': 'True', 'blank': 'True'}),
'survey_id': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['heartbeat.Survey']", 'to_field': "'name'", 'db_column': "'survey_id'"}),
'updated_ts': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
'variation_id': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'version': ('django.db.models.fields.CharField', [], {'default': "u''", 'max_length': '50', 'blank': 'True'})
},
u'heartbeat.survey': {
'Meta': {'object_name': 'Survey'},
'created': ('django.db.models.fields.DateTimeField', [], {'auto_now_add': 'True', 'blank': 'True'}),
'enabled': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '100'})
}
}

complete_apps = ['heartbeat']
5 changes: 4 additions & 1 deletion fjord/heartbeat/models.py
Expand Up @@ -38,6 +38,9 @@ class Answer(ModelBase):
it can **never** be made publicly available.

"""
# The version of the experiment addon.
experiment_version = models.CharField(max_length=50)

# The version of the HTTP POST packet shape. This allows us to
# change how some of the values in the packet are calculated and
# distinguish between different iterations of answers for the same
Expand All @@ -61,7 +64,7 @@ class Answer(ModelBase):
# The id, text and variation of the question being asked.
question_id = models.CharField(max_length=50)
question_text = models.TextField()
variation_id = models.CharField(max_length=50)
variation_id = models.CharField(max_length=100)

# score out of max_score. Use null for no value.
score = models.FloatField(null=True, blank=True)
Expand Down
1 change: 1 addition & 0 deletions fjord/heartbeat/tests/__init__.py
Expand Up @@ -17,6 +17,7 @@ class AnswerFactory(factory.DjangoModelFactory):
class Meta:
model = Answer

experiment_version = '1'
response_version = 1
updated_ts = int(time.time())
survey = factory.SubFactory(SurveyFactory)
Expand Down