Split events/notifications into two tables

This commit is contained in:
Drew DeVault 2017-11-09 21:51:08 -05:00
parent 937890bd65
commit cde30a81b0
7 changed files with 133 additions and 33 deletions

View File

@ -19,7 +19,6 @@ from sqlalchemy.orm import sessionmaker, Session as BaseSession, relationship
Session = sessionmaker()
Base = declarative_base()
class Tracker(Base):
__tablename__ = 'tracker'
id = sa.Column(sa.Integer, primary_key=True)

View File

@ -0,0 +1,75 @@
"""Split event table in two
Revision ID: 6169a5600336
Revises: 132ee194cefe
Create Date: 2017-11-09 18:45:13.828939
"""
# revision identifiers, used by Alembic.
revision = '6169a5600336'
down_revision = '132ee194cefe'
from alembic import op
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker, Session as BaseSession, relationship
Session = sessionmaker()
Base = declarative_base()
class User(Base):
__tablename__ = 'user'
id = sa.Column(sa.Integer, primary_key=True)
class Ticket(Base):
__tablename__ = 'ticket'
id = sa.Column(sa.Integer, primary_key=True)
submitter_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
class TicketComment(Base):
__tablename__ = 'ticket_comment'
id = sa.Column(sa.Integer, primary_key=True)
submitter_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
class Event(Base):
__tablename__ = 'event'
id = sa.Column(sa.Integer, primary_key=True)
created = sa.Column(sa.DateTime, nullable=False)
user_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
ticket_id = sa.Column(sa.Integer, sa.ForeignKey("ticket.id"), nullable=False)
ticket = sa.orm.relationship("Ticket")
comment_id = sa.Column(sa.Integer, sa.ForeignKey("ticket_comment.id"))
comment = sa.orm.relationship("TicketComment")
class EventNotification(Base):
__tablename__ = 'event_notification'
id = sa.Column(sa.Integer, primary_key=True)
created = sa.Column(sa.DateTime, nullable=False)
event_id = sa.Column(sa.Integer, sa.ForeignKey("event.id"), nullable=False)
user_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
def upgrade():
bind = op.get_bind()
session = Session(bind=bind)
op.create_table('event_notification',
sa.Column('id', sa.Integer, primary_key=True),
sa.Column('created', sa.DateTime, nullable=False),
sa.Column('event_id', sa.Integer, sa.ForeignKey("event.id"), nullable=False),
sa.Column('user_id', sa.Integer, sa.ForeignKey("user.id"), nullable=False))
session.commit()
# NOTE: This does not clear out duplicate events. ¯\_(ツ)_/¯
for event in session.query(Event).all():
notification = EventNotification()
notification.created = event.created
notification.event_id = event.id
notification.user_id = event.user_id
if event.comment:
event.user_id = event.comment.submitter_id
else:
event.user_id = event.ticket.submitter_id
session.add(notification)
session.commit()
def downgrade():
op.drop_table('event_notifications')

View File

@ -1,6 +1,6 @@
from flask import Blueprint, render_template
from flask_login import current_user
from todosrht.types import Tracker, Event, EventType
from todosrht.types import Tracker, Event, EventNotification, EventType
html = Blueprint('html', __name__)
@ -12,10 +12,10 @@ def index():
your_trackers = (Tracker.query
.filter(Tracker.owner_id == current_user.id)
.order_by(Tracker.updated.desc())).all()
events = (Event.query
.filter(Event.user_id == current_user.id)
.order_by(Event.created.desc())
.limit(10)).all()
events = [e.event for e in (EventNotification.query
.filter(EventNotification.user_id == current_user.id)
.order_by(EventNotification.created.desc())
.limit(10)).all()]
return render_template("dashboard.html",
your_trackers=your_trackers,
events=events,

View File

@ -4,8 +4,9 @@ from flask import Blueprint, render_template, request, url_for, abort, redirect
from flask import session
from flask_login import current_user
from todosrht.decorators import loginrequired
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess, TicketSeen
from todosrht.types import TicketComment, TicketResolution, Event, EventType
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess
from todosrht.types import TicketComment, TicketResolution, TicketSeen
from todosrht.types import Event, EventType, EventNotification
from todosrht.blueprints.tracker import get_access, get_tracker
from todosrht.email import notify
from srht.config import cfg
@ -145,26 +146,32 @@ def ticket_comment_POST(owner, name, ticket_id):
resolution=resolution.name if resolution else None,
ticket_url=ticket_url.replace("%7E", "~")) # hack
def _add_event(sub):
event = Event()
event.event_type = 0
event.user_id = sub.user_id
event.ticket_id = ticket.id
if comment:
event.event_type |= EventType.comment
event.comment_id = comment.id
if ticket.status != old_status or ticket.resolution != old_resolution:
event.event_type |= EventType.status_change
event.old_status = old_status
event.old_resolution = old_resolution
event.new_status = ticket.status
event.new_resolution = ticket.resolution
db.session.add(event)
event = Event()
event.event_type = 0
event.user_id = current_user.id
event.ticket_id = ticket.id
if comment:
event.event_type |= EventType.comment
event.comment_id = comment.id
if ticket.status != old_status or ticket.resolution != old_resolution:
event.event_type |= EventType.status_change
event.old_status = old_status
event.old_resolution = old_resolution
event.new_status = ticket.status
event.new_resolution = ticket.resolution
db.session.add(event)
db.session.flush()
def _add_notification(sub):
notification = EventNotification()
notification.user_id = sub.user_id
notification.event_id = event.id
db.session.add(notification)
updated_users = set()
for sub in tracker.subscriptions:
updated_users.update([sub.user_id])
_add_event(sub)
_add_notification(sub)
if sub.user_id == current_user.id:
subscribed = True
continue
@ -173,7 +180,7 @@ def ticket_comment_POST(owner, name, ticket_id):
for sub in ticket.subscriptions:
if sub.user_id in updated_users:
continue
_add_event(sub)
_add_notification(sub)
if sub.user_id == current_user.id:
subscribed = True
continue
@ -184,7 +191,7 @@ def ticket_comment_POST(owner, name, ticket_id):
sub.ticket_id = ticket.id
sub.user_id = user.id
db.session.add(sub)
_add_event(sub)
_add_notification(sub)
db.session.commit()

View File

@ -8,7 +8,7 @@ from todosrht.decorators import loginrequired
from todosrht.email import notify
from todosrht.types import Tracker, User, Ticket, TicketStatus, TicketAccess
from todosrht.types import TicketComment, TicketResolution, TicketSubscription
from todosrht.types import TicketSeen, Event, EventType
from todosrht.types import TicketSeen, Event, EventType, EventNotification
from srht.config import cfg
from srht.database import db
from srht.validation import Validation
@ -240,6 +240,12 @@ def tracker_submit_POST(owner, name):
tracker.updated = datetime.utcnow()
# TODO: Handle unique constraint failure (contention) and retry?
db.session.flush()
event = Event()
event.event_type = EventType.created
event.user_id = current_user.id
event.ticket_id = ticket.id
db.session.add(event)
db.session.flush()
ticket_url = url_for("ticket.ticket_GET",
owner="~" + tracker.owner.username,
@ -247,11 +253,10 @@ def tracker_submit_POST(owner, name):
ticket_id=ticket.scoped_id)
for sub in tracker.subscriptions:
event = Event()
event.event_type = EventType.created
event.user_id = sub.user_id
event.ticket_id = ticket.id
db.session.add(event)
notification = EventNotification()
notification.user_id = sub.user_id
notification.event_id = event.id
db.session.add(notification)
if sub.user_id == ticket.submitter_id:
subscribed = True

View File

@ -6,4 +6,4 @@ from .ticketseen import TicketSeen
from .ticket import Ticket
from .ticketsubscription import TicketSubscription
from .ticketcomment import TicketComment
from .event import Event, EventType
from .event import Event, EventType, EventNotification

View File

@ -37,3 +37,17 @@ class Event(Base):
def __repr__(self):
return '<Event {}>'.format(self.id)
class EventNotification(Base):
__tablename__ = 'event_notification'
id = sa.Column(sa.Integer, primary_key=True)
created = sa.Column(sa.DateTime, nullable=False)
event_id = sa.Column(sa.Integer, sa.ForeignKey("event.id"), nullable=False)
event = sa.orm.relationship("Event", backref=sa.orm.backref("notifications"))
user_id = sa.Column(sa.Integer, sa.ForeignKey("user.id"), nullable=False)
user = sa.orm.relationship("User", backref=sa.orm.backref("notifications"))
def __repr__(self):
return '<EventNotification {} {}>'.format(self.id, self.user.username)