Files
zulip/zerver/migrations/0023_rebuild_search_tsvector.py
Zev Benjamin 7b6f6823a5 [manual] Change references to the humbug user, schema, and database to zulip
This commit must be simultaneously deployed on both staging and
prod0.  It also requires completely taking down the app.

To deploy these changes, do:
* check out this commit at /root/zulip on postgres0, postgres1, staging, and prod0

* stop the process_fts_updates job on postgres0 and postgres1
* stop the app on staging and prod0

* do a puppet apply on postgres0, postgres1, staging, and prod0
* move the new client certificates into place on staging and app
* move the new server certificates into place on postgres0 and postgres1
* reload the database config on postgres0 and postgres1 (this might
  actually require a restart)
* run tools/migrate-db on postgres0 as root

* do a deploy through this commit on staging and prod0
* start the process_fts_updates job on postgres0 and postgres1

* do a puppet apply on nagios

(imported from commit 819bdd14326c1425e2d3041a491a8ca3b9716506)
2013-10-26 04:16:27 -04:00

187 lines
12 KiB
Python

# -*- coding: utf-8 -*-
import datetime
from south.db import db
from south.v2 import DataMigration
from django.db import models
from django.conf import settings
import time
class Migration(DataMigration):
def forwards(self, orm):
if "postgres" not in settings.DATABASES["default"]["ENGINE"]:
return
db.start_transaction()
db.execute("DROP TRIGGER zephyr_message_update_search_tsvector ON zephyr_message")
db.execute("""CREATE TRIGGER zephyr_message_update_search_tsvector
BEFORE INSERT OR UPDATE OF subject, rendered_content ON zephyr_message
FOR EACH ROW EXECUTE PROCEDURE tsvector_update_trigger(search_tsvector,
'zulip.english_us_search', subject, rendered_content)""")
db.commit_transaction()
(min_id, max_id) = db.execute("SELECT MIN(id), MAX(id) FROM zephyr_message")[0]
if min_id is not None:
self.set_search_tsvector('zulip.english_us_search', 'rendered_content',
min_id, max_id)
def set_search_tsvector(self, config, column, min_id, max_id):
lower_bound = min_id
batch_size = 1000
query = ("UPDATE zephyr_message SET "
+ "search_tsvector = to_tsvector(%s, "
+ "subject || ' ' || " + column + ") "
+ "WHERE id >= %s AND id < %s")
for upper_bound in xrange(min_id + batch_size, max_id + batch_size, batch_size):
db.start_transaction()
db.execute(query,
params=[config, lower_bound, upper_bound])
db.commit_transaction()
lower_bound = upper_bound
time.sleep(1)
def backwards(self, orm):
if "postgres" not in settings.DATABASES["default"]["ENGINE"]:
return
db.start_transaction()
db.execute("DROP TRIGGER zephyr_message_update_search_tsvector ON zephyr_message")
db.execute("""CREATE TRIGGER zephyr_message_update_search_tsvector
BEFORE INSERT OR UPDATE ON zephyr_message FOR EACH ROW
EXECUTE PROCEDURE tsvector_update_trigger(search_tsvector,
'pg_catalog.english', subject, content)""");
db.commit_transaction()
(min_id, max_id) = db.execute("SELECT MIN(id), MAX(id) FROM zephyr_message")[0]
if min_id is not None:
self.set_search_tsvector('pg_catalog.english', 'content',
min_id, max_id)
models = {
u'zephyr.client': {
'Meta': {'object_name': 'Client'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '30', 'db_index': 'True'})
},
u'zephyr.defaultstream': {
'Meta': {'unique_together': "(('realm', 'stream'),)", 'object_name': 'DefaultStream'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Realm']"}),
'stream': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Stream']"})
},
u'zephyr.huddle': {
'Meta': {'object_name': 'Huddle'},
'huddle_hash': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'})
},
u'zephyr.message': {
'Meta': {'object_name': 'Message'},
'content': ('django.db.models.fields.TextField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'pub_date': ('django.db.models.fields.DateTimeField', [], {'db_index': 'True'}),
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Recipient']"}),
'rendered_content': ('django.db.models.fields.TextField', [], {'null': 'True'}),
'rendered_content_version': ('django.db.models.fields.IntegerField', [], {'null': 'True'}),
'sender': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']"}),
'sending_client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Client']"}),
'subject': ('django.db.models.fields.CharField', [], {'max_length': '60', 'db_index': 'True'})
},
u'zephyr.mituser': {
'Meta': {'object_name': 'MitUser'},
'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.IntegerField', [], {'default': '0'})
},
u'zephyr.preregistrationuser': {
'Meta': {'object_name': 'PreregistrationUser'},
'email': ('django.db.models.fields.EmailField', [], {'max_length': '75'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invited_at': ('django.db.models.fields.DateTimeField', [], {'auto_now': 'True', 'blank': 'True'}),
'referred_by': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']", 'null': 'True'}),
'status': ('django.db.models.fields.IntegerField', [], {'default': '0'}),
'streams': ('django.db.models.fields.related.ManyToManyField', [], {'to': u"orm['zephyr.Stream']", 'null': 'True', 'symmetrical': 'False'})
},
u'zephyr.realm': {
'Meta': {'object_name': 'Realm'},
'domain': ('django.db.models.fields.CharField', [], {'unique': 'True', 'max_length': '40', 'db_index': 'True'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'restricted_to_domain': ('django.db.models.fields.BooleanField', [], {'default': 'True'})
},
u'zephyr.recipient': {
'Meta': {'unique_together': "(('type', 'type_id'),)", 'object_name': 'Recipient'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'type': ('django.db.models.fields.PositiveSmallIntegerField', [], {'db_index': 'True'}),
'type_id': ('django.db.models.fields.IntegerField', [], {'db_index': 'True'})
},
u'zephyr.stream': {
'Meta': {'unique_together': "(('name', 'realm'),)", 'object_name': 'Stream'},
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'invite_only': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
'name': ('django.db.models.fields.CharField', [], {'max_length': '30', 'db_index': 'True'}),
'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Realm']"})
},
u'zephyr.streamcolor': {
'Meta': {'object_name': 'StreamColor'},
'color': ('django.db.models.fields.CharField', [], {'max_length': '10'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'subscription': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Subscription']"})
},
u'zephyr.subscription': {
'Meta': {'unique_together': "(('user_profile', 'recipient'),)", 'object_name': 'Subscription'},
'active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'color': ('django.db.models.fields.CharField', [], {'default': "'#c2c2c2'", 'max_length': '10'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'in_home_view': ('django.db.models.fields.NullBooleanField', [], {'default': 'True', 'null': 'True', 'blank': 'True'}),
'notifications': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'recipient': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Recipient']"}),
'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']"})
},
u'zephyr.useractivity': {
'Meta': {'unique_together': "(('user_profile', 'client', 'query'),)", 'object_name': 'UserActivity'},
'client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Client']"}),
'count': ('django.db.models.fields.IntegerField', [], {}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'last_visit': ('django.db.models.fields.DateTimeField', [], {}),
'query': ('django.db.models.fields.CharField', [], {'max_length': '50', 'db_index': 'True'}),
'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']"})
},
u'zephyr.usermessage': {
'Meta': {'unique_together': "(('user_profile', 'message'),)", 'object_name': 'UserMessage'},
'archived': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'flags': ('django.db.models.fields.BigIntegerField', [], {'default': '0'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'message': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Message']"}),
'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']"})
},
u'zephyr.userpresence': {
'Meta': {'unique_together': "(('user_profile', 'client'),)", 'object_name': 'UserPresence'},
'client': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Client']"}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'status': ('django.db.models.fields.PositiveSmallIntegerField', [], {'default': '1'}),
'timestamp': ('django.db.models.fields.DateTimeField', [], {}),
'user_profile': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.UserProfile']"})
},
u'zephyr.userprofile': {
'Meta': {'object_name': 'UserProfile'},
'api_key': ('django.db.models.fields.CharField', [], {'max_length': '32'}),
'date_joined': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'email': ('django.db.models.fields.EmailField', [], {'unique': 'True', 'max_length': '75', 'db_index': 'True'}),
'enable_desktop_notifications': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'enter_sends': ('django.db.models.fields.NullBooleanField', [], {'default': 'False', 'null': 'True', 'blank': 'True'}),
'full_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
u'id': ('django.db.models.fields.AutoField', [], {'primary_key': 'True'}),
'is_active': ('django.db.models.fields.BooleanField', [], {'default': 'True'}),
'is_staff': ('django.db.models.fields.BooleanField', [], {'default': 'False'}),
'last_login': ('django.db.models.fields.DateTimeField', [], {'default': 'datetime.datetime.now'}),
'last_pointer_updater': ('django.db.models.fields.CharField', [], {'max_length': '64'}),
'password': ('django.db.models.fields.CharField', [], {'max_length': '128'}),
'pointer': ('django.db.models.fields.IntegerField', [], {}),
'realm': ('django.db.models.fields.related.ForeignKey', [], {'to': u"orm['zephyr.Realm']"}),
'short_name': ('django.db.models.fields.CharField', [], {'max_length': '100'}),
'tutorial_status': ('django.db.models.fields.CharField', [], {'default': "'W'", 'max_length': '1'})
}
}
complete_apps = ['zephyr']
symmetrical = True