Merge lp:~ev/oops-repository/whoopsie-daisy into lp:oops-repository

Proposed by Evan
Status: Merged
Approved by: j.c.sackett
Approved revision: 28
Merged at revision: 13
Proposed branch: lp:~ev/oops-repository/whoopsie-daisy
Merge into: lp:oops-repository
Diff against target: 454 lines (+94/-114)
8 files modified
oopsrepository/cassandra.py (+1/-1)
oopsrepository/oopses.py (+0/-94)
oopsrepository/schema.py (+17/-1)
oopsrepository/testing/cassandra.py (+1/-1)
oopsrepository/testing/matchers.py (+11/-2)
oopsrepository/tests/test_matchers.py (+1/-1)
oopsrepository/tests/test_oopses.py (+62/-13)
oopsrepository/tests/test_schema.py (+1/-1)
To merge this branch: bzr merge lp:~ev/oops-repository/whoopsie-daisy
Reviewer Review Type Date Requested Status
j.c.sackett (community) Approve
Robert Collins Pending
Review via email: mp+97714@code.launchpad.net

Description of the change

Apologies for the accidental deletion there.

This branch:
 - Brings oops-repository up to the latest pycassa API.
 - Replaces the insert_bson function with insert_dict, as we want to inspect the contents of the OOPS in the WSGI code to make a determination as to how we're going to process it, and it doesn't make sense to parse the BSON string twice.
 - Adds a bucket method on the oops module to store crashes that are of the same issue in a single collection.
 - Counts the additions to these buckets at a day interval.
 - Adds tests.

To post a comment you must log in.
Revision history for this message
j.c.sackett (jcsackett) wrote :

This largely looks okay to me, but I'm holding off on voting b/c I'm not certain what has changed in oopses.py; I can see the LoC count is different, and I think everything looks alright, but could you post a diff here of just that file against the current trunk?

Or, if someone with greater knowledge of the oops-repository code thinks this is good, that person is welcome to just mark approved and run with it.

review: Needs Information
Revision history for this message
Evan (ev) wrote :
Revision history for this message
j.c.sackett (jcsackett) wrote :

Thanks so much.

This looks good to me.

review: Approve
27. By Evan

Handle unicode data in OOPSes.

28. By Evan

Missed that comment in DESIGN.txt about all the columns being strings. Simplify the previous commit by just setting a default_validation_class.

Revision history for this message
Evan (ev) wrote :

I've added a commit to handle unicode data in OOPSes by setting a default_validation_class of utf8. The previous behavior was causing exceptions as submissions were made to Ubuntu's crash database:
https://pastebin.canonical.com/62948/

I originally implemented this by encoding unicode dictionary keys and values as utf8 in oops-repository, but then I noticed the comment in DESIGN.txt about the columns all being strings. If that interpretation is incorrect, do feel free to take r27 instead of r28.

Revision history for this message
Robert Collins (lifeless) wrote :

This is landable - we need to get you direct push rights, for now, perhaps jc can land it for you.

Revision history for this message
j.c.sackett (jcsackett) wrote :

I'll assume that counts as a vote for "Approve" on your pending, Robert, and I'm happy to land it.

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
=== modified file 'oopsrepository/cassandra.py'
--- oopsrepository/cassandra.py 2011-02-26 19:47:58 +0000
+++ oopsrepository/cassandra.py 2012-03-23 23:37:20 +0000
@@ -6,7 +6,7 @@
66
7"""Things to ease working with cassandra."""7"""Things to ease working with cassandra."""
88
9from pycassa.cassandra.Cassandra import InvalidRequestException9from pycassa.cassandra.ttypes import InvalidRequestException
1010
11def workaround_1779(callable, *args, **kwargs):11def workaround_1779(callable, *args, **kwargs):
12 """Workaround cassandra not being able to do concurrent schema edits.12 """Workaround cassandra not being able to do concurrent schema edits.
1313
=== added file 'oopsrepository/oopses.py'
--- oopsrepository/oopses.py 1970-01-01 00:00:00 +0000
+++ oopsrepository/oopses.py 2012-03-23 23:37:20 +0000
@@ -0,0 +1,116 @@
1# oops-repository is Copyright 2011 Canonical Ltd.
2#
3# Canonical Ltd ("Canonical") distributes the oops-repository source code under
4# the GNU Affero General Public License, version 3 ("AGPLv3"). See the file
5# LICENSE in the source tree for more information.
6
7"""basic operations on oopses in the db."""
8
9import json
10import bson
11import time
12import uuid
13
14import pycassa
15from pycassa.index import create_index_expression, LT, create_index_clause
16from pycassa.cassandra.ttypes import IndexExpression
17
18DAY = 60*60*24
19MONTH = DAY*30
20
21def prune(config):
22 """Remove OOPSES that are over 30 days old."""
23 pool = pycassa.pool.ConnectionPool(config['keyspace'], config['host'])
24 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
25 oops_cf = pycassa.ColumnFamily(pool, 'OOPS')
26 # Find days to prune
27 days = set()
28 prune_to = time.strftime('%Y%m%d', time.gmtime(time.time() - MONTH))
29 for key, _ in dayoops_cf.get_range():
30 if key < prune_to:
31 days.add(key)
32 if not days:
33 return
34 # collect all the oopses (buffers all in memory; may want to make
35 # incremental in future)
36 batch_size = 10000
37 oopses = []
38 for day in days:
39 columns_found = batch_size
40 start_col = ''
41 while columns_found==batch_size:
42 columns = dayoops_cf.get(day, column_start=start_col)
43 columns_found = len(columns)
44 for column, oopsid in columns.items():
45 start_col = column
46 oopses.append(oopsid)
47 # Remove the oopses
48 batch = oops_cf.batch()
49 map(batch.remove, oopses)
50 batch.send()
51 # Clean out the days aggregates
52 # Clean out the days index
53 batch = dayoops_cf.batch()
54 map(batch.remove, days)
55 batch.send()
56
57def insert(config, oopsid, oops_json, user_token=None):
58 """Insert an OOPS into the system.
59
60 :return: The day which the oops was filed under.
61 """
62 # make sure the oops report is a json dict, and break out each key to a
63 # separate column. For now, rather than worrying about typed column values
64 # we just coerce them all to strings.
65 oops_dict = json.loads(oops_json)
66 assert isinstance(oops_dict, dict)
67 insert_dict = {}
68 for key, value in oops_dict.items():
69 insert_dict[key] = json.dumps(value)
70 return _insert(config, oopsid, insert_dict, user_token)
71
72def insert_dict(config, oopsid, oops_dict, user_token=None):
73 """Insert an OOPS into the system.
74
75 :return: The day which the oops was filed under.
76 """
77 assert isinstance(oops_dict, dict)
78 return _insert(config, oopsid, oops_dict, user_token)
79
80def _insert(config, oopsid, insert_dict, user_token=None):
81 pool = pycassa.pool.ConnectionPool(config['keyspace'], config['host'])
82 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
83 oops_cf = pycassa.ColumnFamily(pool, 'OOPS')
84 day_key = time.strftime('%Y%m%d', time.gmtime())
85 now_uuid = uuid.uuid1()
86
87 oops_cf.insert(oopsid, insert_dict)
88 dayoops_cf.insert(day_key, {now_uuid:oopsid})
89 if user_token:
90 useroops_cf = pycassa.ColumnFamily(pool, 'UserOOPS')
91 useroops_cf.insert(user_token, {oopsid : ''})
92
93 return day_key
94
95def bucket(config, oopsid, bucketid):
96 """Adds an OOPS to a bucket, a collection of OOPSes that form a single
97 issue. If the bucket does not exist, it will be created.
98
99 :return: The day which the bucket was filed under.
100 """
101 pool = pycassa.pool.ConnectionPool(config['keyspace'], config['host'])
102 bucket_cf = pycassa.ColumnFamily(pool, 'Buckets')
103 daybucket_cf = pycassa.ColumnFamily(pool, 'DayBuckets')
104 daybucketcount_cf = pycassa.ColumnFamily(pool, 'DayBucketsCount')
105 day_key = time.strftime('%Y%m%d', time.gmtime())
106
107 bucket_cf.insert(bucketid, {oopsid : ''})
108 daybucket_cf.insert((day_key, bucketid), {oopsid : ''})
109 # We have no way of knowing whether an increment has been performed if the
110 # write fails unexpectedly (CASSANDRA-2495). We will apply eventual
111 # consistency to this problem and tolerate slightly inaccurate counts for
112 # the span of a single day, cleaning up once this period has passed. This
113 # will be done by counting the number of columns in DayBuckets for the day
114 # and bucket ID.
115 daybucketcount_cf.add(day_key, bucketid)
116 return day_key
0117
=== removed file 'oopsrepository/oopses.py'
--- oopsrepository/oopses.py 2012-02-21 10:56:50 +0000
+++ oopsrepository/oopses.py 1970-01-01 00:00:00 +0000
@@ -1,94 +0,0 @@
1# oops-repository is Copyright 2011 Canonical Ltd.
2#
3# Canonical Ltd ("Canonical") distributes the oops-repository source code under
4# the GNU Affero General Public License, version 3 ("AGPLv3"). See the file
5# LICENSE in the source tree for more information.
6
7"""basic operations on oopses in the db."""
8
9import json
10import bson
11import time
12import uuid
13
14import pycassa
15from pycassa.index import create_index_expression, LT, create_index_clause
16from pycassa.cassandra.ttypes import IndexExpression
17
18DAY = 60*60*24
19MONTH = DAY*30
20
21def prune(config):
22 """Remove OOPSES that are over 30 days old."""
23 pool = pycassa.connect(config['keyspace'], config['host'])
24 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
25 oops_cf = pycassa.ColumnFamily(pool, 'OOPS')
26 # Find days to prune
27 days = set()
28 prune_to = time.strftime('%Y%m%d', time.gmtime(time.time() - MONTH))
29 for key, _ in dayoops_cf.get_range(columns=()):
30 if key < prune_to:
31 days.add(key)
32 if not days:
33 return
34 # collect all the oopses (buffers all in memory; may want to make
35 # incremental in future)
36 batch_size = 10000
37 oopses = []
38 for day in days:
39 columns_found = batch_size
40 start_col = ''
41 while columns_found==batch_size:
42 columns = dayoops_cf.get(day, column_start=start_col)
43 columns_found = len(columns)
44 for column, oopsid in columns.items():
45 start_col = column
46 oopses.append(oopsid)
47 # Remove the oopses
48 batch = oops_cf.batch()
49 map(batch.remove, oopses)
50 batch.send()
51 # Clean out the days aggregates
52 # Clean out the days index
53 batch = dayoops_cf.batch()
54 map(batch.remove, days)
55 batch.send()
56
57def insert(config, oopsid, oops_json, user_token=None):
58 """Insert an OOPS into the system.
59
60 :return: The day which the oops was filed under.
61 """
62 # make sure the oops report is a json dict, and break out each key to a
63 # separate column. For now, rather than worrying about typed column values
64 # we just coerce them all to strings.
65 oops_dict = json.loads(oops_json)
66 assert isinstance(oops_dict, dict)
67 insert_dict = {}
68 for key, value in oops_dict.items():
69 insert_dict[key] = json.dumps(value)
70 return _insert(config, oopsid, insert_dict, user_token)
71
72def insert_bson(config, oopsid, oops_bson, user_token=None):
73 """Insert an OOPS into the system.
74
75 :return: The day which the oops was filed under.
76 """
77 oops_dict = bson.BSON(oops_bson)
78 insert_dict = oops_dict.to_dict()
79 return _insert(config, oopsid, insert_dict, user_token)
80
81def _insert(config, oopsid, insert_dict, user_token=None):
82 pool = pycassa.connect(config['keyspace'], config['host'])
83 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
84 oops_cf = pycassa.ColumnFamily(pool, 'OOPS')
85 day_key = time.strftime('%Y%m%d', time.gmtime())
86 now_uuid = uuid.uuid1()
87
88 oops_cf.insert(oopsid, insert_dict)
89 dayoops_cf.insert(day_key, {now_uuid:oopsid})
90 if user_token:
91 useroops_cf = pycassa.ColumnFamily(pool, 'UserOOPS')
92 useroops_cf.insert(user_token, {oopsid : ''})
93
94 return day_key
950
=== modified file 'oopsrepository/schema.py'
--- oopsrepository/schema.py 2011-04-03 11:14:12 +0000
+++ oopsrepository/schema.py 2012-03-23 23:37:20 +0000
@@ -6,6 +6,11 @@
66
7"""The schema for oopsrepository."""7"""The schema for oopsrepository."""
88
9from pycassa.types import (
10 CompositeType,
11 UTF8Type,
12 CounterColumnType,
13 )
9from pycassa.system_manager import (14from pycassa.system_manager import (
10 LONG_TYPE,15 LONG_TYPE,
11 SystemManager,16 SystemManager,
@@ -28,9 +33,20 @@
28 mgr = SystemManager()33 mgr = SystemManager()
29 try:34 try:
30 workaround_1779(mgr.create_column_family, keyspace, 'OOPS',35 workaround_1779(mgr.create_column_family, keyspace, 'OOPS',
31 comparator_type=UTF8_TYPE)36 comparator_type=UTF8_TYPE, default_validation_class=UTF8_TYPE)
32 workaround_1779(mgr.create_column_family, keyspace, 'DayOOPS',37 workaround_1779(mgr.create_column_family, keyspace, 'DayOOPS',
33 comparator_type=TIME_UUID_TYPE)38 comparator_type=TIME_UUID_TYPE)
39 workaround_1779(mgr.create_column_family, keyspace, 'UserOOPS',
40 comparator_type=UTF8_TYPE)
41 workaround_1779(mgr.create_column_family, keyspace, 'Buckets',
42 comparator_type=UTF8_TYPE)
43 # TODO It might be more performant to use just the date for the key and
44 # a composite key of the bucket_id and the oops_id as the column name.
45 composite = CompositeType(UTF8Type(), UTF8Type())
46 workaround_1779(mgr.create_column_family, keyspace, 'DayBuckets',
47 comparator_type=UTF8_TYPE, key_validation_class=composite)
48 workaround_1779(mgr.create_column_family, keyspace, 'DayBucketsCount',
49 comparator_type=UTF8_TYPE, default_validation_class=CounterColumnType())
34 finally:50 finally:
35 mgr.close()51 mgr.close()
3652
3753
=== modified file 'oopsrepository/testing/cassandra.py'
--- oopsrepository/testing/cassandra.py 2011-02-27 04:46:26 +0000
+++ oopsrepository/testing/cassandra.py 2012-03-23 23:37:20 +0000
@@ -28,7 +28,7 @@
28 self.keyspace = os.path.basename(tempdir.path)28 self.keyspace = os.path.basename(tempdir.path)
29 self.mgr = SystemManager()29 self.mgr = SystemManager()
30 workaround_1779(self.mgr.create_keyspace, self.keyspace,30 workaround_1779(self.mgr.create_keyspace, self.keyspace,
31 replication_factor=1)31 pycassa.SIMPLE_STRATEGY, {'replication_factor' : '1'})
32 self.addCleanup(workaround_1779, self.mgr.drop_keyspace,32 self.addCleanup(workaround_1779, self.mgr.drop_keyspace,
33 self.keyspace)33 self.keyspace)
3434
3535
=== modified file 'oopsrepository/testing/matchers.py'
--- oopsrepository/testing/matchers.py 2011-04-03 11:14:12 +0000
+++ oopsrepository/testing/matchers.py 2012-03-23 23:37:20 +0000
@@ -11,7 +11,7 @@
11import uuid11import uuid
1212
13import pycassa13import pycassa
14from pycassa.cassandra.Cassandra import NotFoundException14from pycassa.cassandra.ttypes import NotFoundException
15from testtools.matchers import Matcher, Mismatch15from testtools.matchers import Matcher, Mismatch
1616
1717
@@ -22,12 +22,21 @@
22 """22 """
2323
24 def match(self, keyspace):24 def match(self, keyspace):
25 pool = pycassa.connect(keyspace)25 pool = pycassa.ConnectionPool(keyspace, ['localhost:9160'])
26 try:26 try:
27 cf = pycassa.ColumnFamily(pool, 'OOPS')27 cf = pycassa.ColumnFamily(pool, 'OOPS')
28 cf.insert('key',28 cf.insert('key',
29 {"date":json.dumps(time.time()), "URL":'a bit boring'})29 {"date":json.dumps(time.time()), "URL":'a bit boring'})
30 cf = pycassa.ColumnFamily(pool, 'DayOOPS')30 cf = pycassa.ColumnFamily(pool, 'DayOOPS')
31 cf.insert('20100212', {uuid.uuid1(): 'key'})31 cf.insert('20100212', {uuid.uuid1(): 'key'})
32 cf = pycassa.ColumnFamily(pool, 'UserOOPS')
33 cf.insert('user-token', {'key':''})
34
35 cf = pycassa.ColumnFamily(pool, 'Buckets')
36 cf.insert('/bin/bash:11:x86_64:[vdso]+70c:...', {'key':''})
37 cf = pycassa.ColumnFamily(pool, 'DayBuckets')
38 cf.insert(('20100212', '/bin/bash:11:x86_64:[vdso]+70c:...'), {'key':''})
39 cf = pycassa.ColumnFamily(pool, 'DayBucketsCount')
40 cf.add('20100212', '/bin/bash:11:x86_64:[vdso]+70c:...', 13)
32 except NotFoundException as e:41 except NotFoundException as e:
33 return Mismatch(e.why)42 return Mismatch(e.why)
3443
=== modified file 'oopsrepository/tests/test_matchers.py'
--- oopsrepository/tests/test_matchers.py 2011-02-27 04:46:26 +0000
+++ oopsrepository/tests/test_matchers.py 2012-03-23 23:37:20 +0000
@@ -16,6 +16,6 @@
16 def test_creates_columnfamily(self):16 def test_creates_columnfamily(self):
17 keyspace = self.useFixture(TemporaryKeyspace()).keyspace17 keyspace = self.useFixture(TemporaryKeyspace()).keyspace
18 self.assertNotEqual(None, HasOOPSSchema().match(keyspace))18 self.assertNotEqual(None, HasOOPSSchema().match(keyspace))
19 config = dict(keyspace=keyspace)19 config = dict(keyspace=keyspace, host=['localhost:9160'])
20 schema.create(config)20 schema.create(config)
21 self.assertThat(keyspace, HasOOPSSchema())21 self.assertThat(keyspace, HasOOPSSchema())
2222
=== modified file 'oopsrepository/tests/test_oopses.py'
--- oopsrepository/tests/test_oopses.py 2011-04-03 11:14:12 +0000
+++ oopsrepository/tests/test_oopses.py 2012-03-23 23:37:20 +0000
@@ -1,3 +1,4 @@
1# -*- coding: utf-8; -*-
1# oops-repository is Copyright 2011 Canonical Ltd.2# oops-repository is Copyright 2011 Canonical Ltd.
2#3#
3# Canonical Ltd ("Canonical") distributes the oops-repository source code under4# Canonical Ltd ("Canonical") distributes the oops-repository source code under
@@ -19,10 +20,10 @@
1920
20 def test_fresh_oops_kept(self):21 def test_fresh_oops_kept(self):
21 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace22 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
22 config = dict(keyspace=keyspace)23 config = dict(keyspace=keyspace, host=['localhost:9160'])
23 day_key = oopses.insert(config, 'key',24 day_key = oopses.insert(config, 'key',
24 json.dumps({"date":time.time(), "URL":'a bit boring'}))25 json.dumps({"date":time.time(), "URL":'a bit boring'}))
25 pool = pycassa.connect(keyspace)26 pool = pycassa.ConnectionPool(keyspace, ['localhost:9160'])
26 dayoopses_cf = pycassa.ColumnFamily(pool, 'DayOOPS')27 dayoopses_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
27 oopses_cf = pycassa.ColumnFamily(pool, 'OOPS')28 oopses_cf = pycassa.ColumnFamily(pool, 'OOPS')
28 oopses.prune(config)29 oopses.prune(config)
@@ -32,8 +33,8 @@
3233
33 def test_old_oops_deleted(self):34 def test_old_oops_deleted(self):
34 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace35 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
35 config = dict(keyspace=keyspace)36 config = dict(keyspace=keyspace, host=['localhost:9160'])
36 pool = pycassa.connect(keyspace)37 pool = pycassa.ConnectionPool(keyspace, ['localhost:9160'])
37 dayoopses_cf = pycassa.ColumnFamily(pool, 'DayOOPS')38 dayoopses_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
38 datestamp = time.time() - oopses.MONTH - oopses.DAY39 datestamp = time.time() - oopses.MONTH - oopses.DAY
39 day_key = time.strftime('%Y%m%d', time.gmtime(datestamp))40 day_key = time.strftime('%Y%m%d', time.gmtime(datestamp))
@@ -50,20 +51,68 @@
5051
51class TestInsert(TestCase):52class TestInsert(TestCase):
5253
53 def test_insert_oops(self):54 def _test_insert_check(self, keyspace, oopsid, day_key, value=None):
54 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace55 pool = pycassa.ConnectionPool(keyspace, host=['localhost:9160'])
55 oopsid = 'booyah'
56 oops = json.dumps({'duration': 13000})
57 config = dict(keyspace=keyspace)
58 day_key = oopses.insert(config, oopsid, oops)
59 pool = pycassa.connect(keyspace)
60 oopses_cf = pycassa.ColumnFamily(pool, 'OOPS')56 oopses_cf = pycassa.ColumnFamily(pool, 'OOPS')
57 if value is None:
58 value = '13000'
61 # The oops is retrievable59 # The oops is retrievable
62 columns = oopses_cf.get(oopsid)60 columns = oopses_cf.get(oopsid)
63 self.assertEqual('13000', columns['duration'])61 self.assertEqual(value, columns['duration'])
64 # The oops has been indexed by day62 # The oops has been indexed by day
65 pool = pycassa.connect(keyspace)63 pool = pycassa.ConnectionPool(keyspace, host=['localhost:9160'])
66 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')64 dayoops_cf = pycassa.ColumnFamily(pool, 'DayOOPS')
67 oops_refs = dayoops_cf.get(day_key)65 oops_refs = dayoops_cf.get(day_key)
68 self.assertEqual([oopsid], oops_refs.values())66 self.assertEqual([oopsid], oops_refs.values())
69 ## TODO - the aggregates for the OOPS have been updated.67 ## TODO - the aggregates for the OOPS have been updated.
68
69 def test_insert_oops(self):
70 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
71 oopsid = 'booyah'
72 oops = json.dumps({'duration': 13000})
73 config = dict(keyspace=keyspace, host=['localhost:9160'])
74 day_key = oopses.insert(config, oopsid, oops)
75 self._test_insert_check(keyspace, oopsid, day_key)
76
77 def test_insert_oops_dict(self):
78 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
79 oopsid = 'booyah'
80 oops = {'duration': '13000'}
81 config = dict(keyspace=keyspace, host=['localhost:9160'])
82 day_key = oopses.insert_dict(config, oopsid, oops)
83 self._test_insert_check(keyspace, oopsid, day_key)
84
85 def test_insert_unicode(self):
86 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
87 oopsid = 'booyah'
88 oops = {'duration': u'♥'}
89 config = dict(keyspace=keyspace, host=['localhost:9160'])
90 day_key = oopses.insert_dict(config, oopsid, oops)
91 self._test_insert_check(keyspace, oopsid, day_key, value=u'♥')
92
93class TestBucket(TestCase):
94
95 def test_insert_bucket(self):
96 keyspace = self.useFixture(TemporaryOOPSDB()).keyspace
97 config = dict(keyspace=keyspace, host=['localhost:9160'])
98 oopsid = 'booyah'
99 oops = json.dumps({'duration': 13000})
100 oopses.insert(config, oopsid, oops)
101 day_key = oopses.bucket(config, oopsid, 'bucket-key')
102
103 pool = pycassa.ConnectionPool(keyspace, ['localhost:9160'])
104 bucket_cf = pycassa.ColumnFamily(pool, 'Buckets')
105 daybucketcount_cf = pycassa.ColumnFamily(pool, 'DayBucketsCount')
106
107 oops_refs = bucket_cf.get('bucket-key')
108 self.assertEqual([oopsid], oops_refs.keys())
109 self.assertEqual(
110 daybucketcount_cf.get(day_key, ['bucket-key']).values(), [1])
111
112 oopsid = 'foobar'
113 oops = json.dumps({'wibbles': 12})
114 oopses.insert(config, oopsid, oops)
115 day_key = oopses.bucket(config, oopsid, 'bucket-key')
116 self.assertEqual(
117 daybucketcount_cf.get(day_key, ['bucket-key']).values(), [2])
118
70119
=== modified file 'oopsrepository/tests/test_schema.py'
--- oopsrepository/tests/test_schema.py 2011-02-27 04:46:26 +0000
+++ oopsrepository/tests/test_schema.py 2012-03-23 23:37:20 +0000
@@ -16,6 +16,6 @@
1616
17 def test_creates_columnfamily(self):17 def test_creates_columnfamily(self):
18 keyspace = self.useFixture(TemporaryKeyspace()).keyspace18 keyspace = self.useFixture(TemporaryKeyspace()).keyspace
19 config = dict(keyspace=keyspace)19 config = dict(keyspace=keyspace, host=['localhost:9160'])
20 schema.create(config)20 schema.create(config)
21 self.assertThat(keyspace, HasOOPSSchema())21 self.assertThat(keyspace, HasOOPSSchema())

Subscribers

People subscribed via source and target branches

to all changes: