Skip to content

Commit c4c3d9c

Browse files
author
[Arusey]
committed
CON-72-story(notifications): admin receives notification when device is not seen in a while
- setup queue manager for when notifications are sent - implement notifications when device is not seen in a while [Delivers CON-72]
1 parent c423e3e commit c4c3d9c

File tree

10 files changed

+101
-72
lines changed

10 files changed

+101
-72
lines changed
Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
from datetime import datetime
2+
from api.devices.models import Devices as DevicesModel
3+
from utilities.utility import update_entity_fields
4+
import celery
5+
6+
7+
@celery.task(name='check-device-last-seen')
8+
def notify_when_device_is_offline(**kwargs):
9+
query = DevicesModel.query
10+
active_devices = query.filter(DevicesModel.activity == "online").all()
11+
for device in active_devices:
12+
device_last_seen = device.last_seen
13+
current_time = datetime.now()
14+
duration_offline = current_time - device_last_seen
15+
16+
if duration_offline.days > 1:
17+
update_entity_fields(device, activity="offline")
18+
device.save()
19+
return active_devices
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
from datetime import timedelta
2+
beat_schedule = {
3+
'run-check-device-last-seen-hourly': {
4+
'task': 'check_device_last_seen',
5+
'schedule': timedelta(seconds=5)
6+
}
7+
}

admin_notifications/models.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,5 +18,4 @@ class AdminNotification(Base, Utility):
1818
Integer,
1919
ForeignKey('locations.id', ondelete="CASCADE"),
2020
nullable=True
21-
)
22-
21+
)
Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
"""add activity column to devices table
2+
3+
Revision ID: 1b53553ddacf
4+
Revises: c65718cd4ed8
5+
Create Date: 2019-06-22 12:59:24.591339
6+
7+
"""
8+
from alembic import op
9+
import sqlalchemy as sa
10+
from sqlalchemy.dialects import postgresql
11+
12+
13+
# revision identifiers, used by Alembic.
14+
revision = '1b53553ddacf'
15+
down_revision = 'c65718cd4ed8'
16+
branch_labels = None
17+
depends_on = None
18+
19+
20+
def upgrade():
21+
# ### commands auto generated by Alembic - please adjust! ###
22+
activitytype = postgresql.ENUM('online', 'offline', name='activitytype')
23+
activitytype.create(op.get_bind())
24+
op.add_column('devices', sa.Column('activity', sa.Enum(
25+
'online', 'offline', name='activitytype'), nullable=True))
26+
27+
# ### end Alembic commands ###
28+
29+
30+
def downgrade():
31+
# ### commands auto generated by Alembic - please adjust! ###
32+
op.drop_column('devices', 'activity')
33+
op.execute("DROP TYPE activitytype;")
34+
# ### end Alembic commands ###

api/devices/models.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,22 +1,23 @@
1-
from sqlalchemy import (Column, String, Integer, DateTime, ForeignKey)
1+
from sqlalchemy import (Column, String, Integer, DateTime, ForeignKey, Enum)
22
from sqlalchemy.schema import Sequence
33
from sqlalchemy.orm import relationship
44

55
from helpers.database import Base
66
from utilities.validations import validate_empty_fields
7-
from utilities.utility import Utility
7+
from utilities.utility import Utility, ActivityType
88

99

1010
class Devices(Base, Utility):
1111
__tablename__ = 'devices'
12-
id = Column(Integer, Sequence('devices_id_seq', start=1, increment=1), primary_key=True) # noqa
12+
id = Column(Integer, Sequence('devices_id_seq', start=1, increment=1), primary_key=True) # noqa
1313
name = Column(String, nullable=False)
1414
device_type = Column(String, nullable=False)
1515
date_added = Column(DateTime, nullable=False)
1616
last_seen = Column(DateTime, nullable=False)
1717
location = Column(String, nullable=False)
1818
room_id = Column(Integer, ForeignKey('rooms.id', ondelete="CASCADE"))
1919
room = relationship('Room')
20+
activity = Column(Enum(ActivityType), default="active")
2021

2122
def __init__(self, **kwargs):
2223
validate_empty_fields(**kwargs)

app.py

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
from flask_graphql import GraphQLView
44
from flask_cors import CORS
55
from flask_json import FlaskJSON
6-
from flask_socketio import SocketIO
76

87
from flask_mail import Mail
98
from config import config
@@ -20,7 +19,6 @@ def create_app(config_name):
2019
app = Flask(__name__)
2120
CORS(app)
2221
FlaskJSON(app)
23-
SocketIO(app)
2422
app.config.from_object(config[config_name])
2523
config[config_name].init_app(app)
2624
mail.init_app(app)

cworker.py

Lines changed: 15 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,26 @@
11
import os
2-
32
from celery import Celery
43
from app import create_app
5-
4+
from admin_notifications.helpers.queue_manager import beat_schedule
65

76
app = create_app(os.getenv('APP_SETTINGS') or 'default')
87
app.app_context().push()
98

109

10+
app.config.update(
11+
CELERY_BROKER_URL='redis://localhost:6379',
12+
CELERY_RESULT_BACKEND='redis://localhost:6379',
13+
# CELERY_ACCEPT_CONTENT=['json'],
14+
CELERYBEAT_SCHEDULE=beat_schedule
15+
)
16+
17+
1118
def make_celery(app):
12-
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
19+
celery = Celery(app.name, broker=app.config['CELERY_BROKER_URL'], include=['admin_notifications.helpers.device_last_seen'], # noqa 501
20+
backend=app.config['CELERY_BROKER_URL'])
21+
1322
celery.conf.update(app.config)
23+
celery.conf.enable_utc = False
1424
TaskBase = celery.Task
1525

1626
class ContextTask(TaskBase):
@@ -24,3 +34,5 @@ def __call__(self, *args, **kwargs):
2434

2535

2636
celery = make_celery(app)
37+
celery_scheduler = Celery(app.name, broker=app.config['CELERY_BROKER_URL'])
38+
celery_scheduler.conf.update(app.config)

helpers/email/email_setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ def __init__(
3030
html=self.template,
3131
sender=self.sender)
3232

33-
@celery.task
33+
@celery.task(name='asynchronous-email-notifications')
3434
def send_async_email(msg_dict):
3535
mail = Mail()
3636
msg = Message()

requirements.txt

Lines changed: 14 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -1,86 +1,39 @@
11
alembic==0.9.8
2-
amqp==1.4.9
3-
aniso8601==3.0.2
4-
anyjson==0.3.3
5-
astroid==2.2.5
6-
attrs==19.1.0
7-
autopep8==1.4.4
8-
billiard==3.3.0.23
9-
blinker==1.4
102
bugsnag==3.4.2
3+
blinker==1.4
114
celery==3.1.17
12-
certifi==2019.3.9
13-
chardet==3.0.4
14-
Click==7.0
155
coverage==4.5.1
16-
coveralls==1.8.0
17-
decorator==4.4.0
18-
docopt==0.6.2
19-
flake8==3.5.0
206
Flask==0.12.2
217
Flask-Cors==3.0.4
22-
Flask-GraphQL==1.4.1
238
Flask-JSON==0.3.2
24-
Flask-Mail==0.9.1
259
Flask-Script==2.0.6
26-
Flask-SocketIO==4.1.0
27-
Flask-Testing==0.7.1
10+
Flask-GraphQL==1.4.1
11+
Flask-Mail==0.9.1
2812
google-api-python-client==1.6.7
29-
graphene==2.1
3013
graphene-sqlalchemy==2.0.0
31-
graphql-core==2.2
32-
graphql-relay==0.4.5
33-
httplib2==0.13.0
34-
idna==2.8
14+
graphene==2.1
3515
imgkit==1.0.1
36-
iso8601==0.1.12
37-
isort==4.3.20
38-
itsdangerous==1.1.0
39-
Jinja2==2.10.1
40-
kombu==3.0.37
41-
lazy-object-proxy==1.4.1
42-
Mako==1.0.12
4316
MarkupSafe==1.0
44-
mccabe==0.6.1
4517
more-itertools==4.1.0
46-
nose==1.3.7
4718
numpy==1.15.2
48-
oauth2client==4.1.3
4919
opencv-python==3.4.3.18
5020
pandas==0.23.4
51-
pdfkit==0.6.1
5221
Pillow==5.3.0
53-
pluggy==0.6.0
54-
promise==2.2.1
22+
pdfkit==0.6.1
5523
psycopg2-binary==2.7.4
5624
py==1.5.3
57-
pyasn1==0.4.5
58-
pyasn1-modules==0.2.5
59-
pycodestyle==2.3.1
60-
pyflakes==1.6.0
61-
PyJWT==1.6.4
62-
pylint==2.3.1
6325
pytest==3.5.0
6426
python-dateutil==2.7.0
65-
python-editor==1.0.3
66-
python-engineio==3.8.1
67-
python-socketio==4.1.0
68-
pytz==2019.1
27+
PyJWT==1.6.4
6928
redis==2.10.3
70-
requests==2.22.0
71-
rsa==4.0
72-
Rx==1.6.1
73-
singledispatch==3.4.0.3
74-
six==1.12.0
29+
nose==1.3.7
30+
python-editor==1.0.3
7531
SQLAlchemy==1.2.6
76-
SQLAlchemy-Utils==0.33.2
7732
tox==3.0.0
78-
typed-ast==1.4.0
79-
typing==3.6.4
80-
uritemplate==3.0.0
81-
urllib3==1.25.3
82-
validators==0.12.4
33+
SQLAlchemy-Utils==0.33.2
8334
virtualenv==15.2.0
84-
WebOb==1.8.5
85-
Werkzeug==0.15.4
86-
wrapt==1.11.1
35+
Flask-Testing==0.7.1
36+
typing==3.6.4
37+
flake8==3.5.0
38+
coveralls
39+
validators==0.12.4

utilities/utility.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,12 @@ class QuestionType(enum.Enum):
8787
check = "check"
8888
textarea = "textarea"
8989

90+
9091
class StatusType(enum.Enum):
9192
read = "read"
9293
unread = "unread"
94+
95+
96+
class ActivityType(enum.Enum):
97+
online = "online"
98+
offline = "offline"

0 commit comments

Comments
 (0)