MVP task architecture

This commit is contained in:
Daniel Ternyak 2019-01-27 22:59:15 -06:00
parent 7e41de9c81
commit b9a88d7276
No known key found for this signature in database
GPG Key ID: DF212D2DC5D0E245
7 changed files with 152 additions and 1 deletions

View File

@ -5,7 +5,7 @@ from flask import Flask
from flask_cors import CORS
from flask_security import SQLAlchemyUserDatastore
from flask_sslify import SSLify
from grant import commands, proposal, user, comment, milestone, admin, email, blockchain
from grant import commands, proposal, user, comment, milestone, admin, email, blockchain, task
from grant.extensions import bcrypt, migrate, db, ma, security
from grant.settings import SENTRY_RELEASE, ENV
from sentry_sdk.integrations.flask import FlaskIntegration
@ -53,6 +53,7 @@ def register_blueprints(app):
app.register_blueprint(admin.views.blueprint)
app.register_blueprint(email.views.blueprint)
app.register_blueprint(blockchain.views.blueprint)
app.register_blueprint(task.views.blueprint)
def register_shellcontext(app):
@ -75,3 +76,4 @@ def register_commands(app):
app.cli.add_command(proposal.commands.create_proposal)
app.cli.add_command(user.commands.delete_user)
app.cli.add_command(admin.commands.gen_admin_auth)
app.cli.add_command(task.commands.create_task)

View File

@ -0,0 +1,5 @@
from . import models
from . import views
from . import commands
from . import jobs

View File

@ -0,0 +1,17 @@
import ast
from datetime import datetime
import click
from flask.cli import with_appcontext
from .models import Task, db
@click.command()
@click.argument('job_id')
@click.argument('blob')
@with_appcontext
def create_task(job_id, blob):
task = Task(job_id, ast.literal_eval(blob), datetime.now())
db.session.add(task)
db.session.commit()

View File

@ -0,0 +1,18 @@
from grant.extensions import db
def proposal_reminder(task_id):
from grant.task.models import Task
task = Task.query.filter_by(id=task_id).first()
from grant.proposal.models import Proposal
proposal = Proposal.query.filter_by(id=task.blob["proposal_id"]).first()
# TODO - replace with email
print(proposal)
task.completed = True
db.session.add(task)
db.session.commit()
JOBS = {
1: proposal_reminder
}

View File

@ -0,0 +1,58 @@
import json
from grant.extensions import ma, db
from sqlalchemy.ext import mutable
class JsonEncodedDict(db.TypeDecorator):
"""Enables JSON storage by encoding and decoding on the fly."""
impl = db.Text
def process_bind_param(self, value, dialect):
if value is None:
return '{}'
else:
return json.dumps(value)
def process_result_value(self, value, dialect):
if value is None:
return {}
else:
return json.loads(value)
mutable.MutableDict.associate_with(JsonEncodedDict)
class Task(db.Model):
__tablename__ = 'task'
id = db.Column(db.Integer(), primary_key=True)
job_id = db.Column(db.Integer(), nullable=False)
blob = db.Column(JsonEncodedDict, nullable=False)
execute_after = db.Column(db.DateTime, nullable=False)
completed = db.Column(db.Boolean, default=False)
def __init__(self, job_id, blob, execute_after, completed=False):
assert job_id in list(JOBS.keys()), "Not a valid job"
self.job_id = job_id
self.blob = blob
self.execute_after = execute_after
self.completed = completed
class TaskSchema(ma.Schema):
class Meta:
model = Task
# Fields to expose
fields = (
"id",
"job_id",
"blob",
"execute_after",
"completed"
)
task_schema = TaskSchema()
tasks_schema = TaskSchema(many=True)

View File

@ -0,0 +1,15 @@
from datetime import datetime
from flask import Blueprint, jsonify
from grant.task.jobs import JOBS
from grant.task.models import Task, tasks_schema
blueprint = Blueprint("task", __name__, url_prefix="/api/v1/task")
@blueprint.route("/", methods=["GET"])
def task():
tasks = Task.query.filter(Task.execute_after <= datetime.now()).all()
for each_task in tasks:
JOBS[each_task.job_id](each_task.id)
return jsonify(tasks_schema.dump(tasks))

View File

@ -0,0 +1,36 @@
"""empty message
Revision ID: bb9c6d733952
Revises: e0d970ed6500
Create Date: 2019-01-27 21:58:45.680009
"""
from alembic import op
import sqlalchemy as sa
from grant.task.models import JsonEncodedDict
# revision identifiers, used by Alembic.
revision = 'bb9c6d733952'
down_revision = 'e0d970ed6500'
branch_labels = None
depends_on = None
def upgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.create_table('task',
sa.Column('id', sa.Integer(), nullable=False),
sa.Column('job_id', sa.Integer(), nullable=False),
sa.Column('blob', JsonEncodedDict(), nullable=False),
sa.Column('execute_after', sa.DateTime(), nullable=False),
sa.Column('completed', sa.Boolean(), nullable=True),
sa.PrimaryKeyConstraint('id')
)
# ### end Alembic commands ###
def downgrade():
# ### commands auto generated by Alembic - please adjust! ###
op.drop_table('task')
# ### end Alembic commands ###