Some progress with moving over to sql keyval

This commit is contained in:
Jeremy Zhang 2017-04-23 23:02:03 -07:00
parent b3a219e58d
commit a212ca1052
6 changed files with 65 additions and 26 deletions

View File

@ -15,7 +15,7 @@ app.config['SQLALCHEMY_DATABASE_URI'] = config['database-uri']
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Suppress the warning/no need this on for now. app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False # Suppress the warning/no need this on for now.
app.config['RATELIMIT_HEADERS_ENABLED'] = True app.config['RATELIMIT_HEADERS_ENABLED'] = True
app.config['SQLALCHEMY_POOL_RECYCLE'] = 250 app.config['SQLALCHEMY_POOL_RECYCLE'] = 250
app.config['RATELIMIT_STORAGE_URL'] = 'redislite://redislite.db' app.config['RATELIMIT_STORAGE_URL'] = 'keyvalprops://'
app.secret_key = config['app-secret'] app.secret_key = config['app-secret']
db.init_app(app) db.init_app(app)
@ -29,9 +29,3 @@ app.register_blueprint(blueprints.embed.embed, url_prefix="/embed", template_fol
@app.route("/") @app.route("/")
def index(): def index():
return render_template("index.html.j2") return render_template("index.html.j2")
@app.route("/oldembed/<guildid>/<channelid>")
def embed_get(guildid, channelid):
if 'username' not in session:
return redirect(url_for("get_set_username", guildid=guildid, channelid=channelid))
return render_template("embed.html")

View File

@ -1,10 +1,9 @@
from flask_sqlalchemy import SQLAlchemy from flask_sqlalchemy import SQLAlchemy
db = SQLAlchemy() db = SQLAlchemy()
from guilds import Guilds from guilds import Guilds
from unauthenticated_users import UnauthenticatedUsers from unauthenticated_users import UnauthenticatedUsers
from unauthenticated_bans import UnauthenticatedBans from unauthenticated_bans import UnauthenticatedBans
from authenticated_users import AuthenticatedUsers from authenticated_users import AuthenticatedUsers
from custom_redislite import LimitsRedisLite from keyvalue_properties import KeyValueProperties, set_keyvalproperty, get_keyvalproperty, getexpir_keyvalproperty, setexpir_keyvalproperty, ifexists_keyvalproperty, delete_keyvalproperty
from keyvalue_properties import set_keyvalproperty, get_keyvalproperty, getexpir_keyvalproperty, setexpir_keyvalproperty

View File

@ -1,5 +1,7 @@
from titanembeds.database import db from titanembeds.database import db
from datetime import datetime from datetime import datetime, timedelta
from limits.storage import Storage
import time
def set_keyvalproperty(key, value, expiration=None): def set_keyvalproperty(key, value, expiration=None):
q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key) q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key)
@ -22,8 +24,10 @@ def getexpir_keyvalproperty(key):
q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key) q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key)
now = datetime.now() now = datetime.now()
if q.count() > 0 and (q.first().expiration is not None and q.first().expiration > now): if q.count() > 0 and (q.first().expiration is not None and q.first().expiration > now):
return q.first().expiration print q.first().expiration
return None print datetime.now().strftime("%Y-%m-%d %H:%M:%S")
return int(q.first().expiration.strftime('%s'))
return 0
def setexpir_keyvalproperty(key, expiration=None): def setexpir_keyvalproperty(key, expiration=None):
q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key) q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key)
@ -34,10 +38,20 @@ def setexpir_keyvalproperty(key, expiration=None):
q.first().expiration = None q.first().expiration = None
db.session.commit() db.session.commit()
def ifexists_keyvalproperty(key):
q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key)
return q.count() > 0
def delete_keyvalproperty(key):
q = db.session.query(KeyValueProperties).filter(KeyValueProperties.key == key).first()
if q:
db.session.delete(q)
db.session.commit()
class KeyValueProperties(db.Model): class KeyValueProperties(db.Model):
__tablename__ = "keyvalue_properties" __tablename__ = "keyvalue_properties"
id = db.Column(db.Integer, primary_key=True) # Auto incremented id id = db.Column(db.Integer, primary_key=True) # Auto incremented id
key = db.Column(db.String(32)) # Property Key key = db.Column(db.String(255)) # Property Key
value = db.Column(db.Text()) # Property value value = db.Column(db.Text()) # Property value
expiration = db.Column(db.TIMESTAMP) # Suggested Expiration for value (None = no expire) in secs expiration = db.Column(db.TIMESTAMP) # Suggested Expiration for value (None = no expire) in secs
@ -45,6 +59,38 @@ class KeyValueProperties(db.Model):
self.key = key self.key = key
self.value = value self.value = value
if expiration: if expiration:
self.expiration = datetime.datetime.now() + datetime.timedelta(seconds = expiration) self.expiration = datetime.now() + timedelta(seconds = expiration)
else: else:
self.expiration = None self.expiration = None
class LimitsKeyValueProperties(Storage): # For Python Limits
STORAGE_SCHEME = "keyvalprops"
def __init__(self, uri, **options):
pass
def check(self):
return True
def get_expiry(self, key):
return getexpir_keyvalproperty(key) + time.time()
def incr(self, key, expiry, elastic_expiry=False):
if not ifexists_keyvalproperty(key):
set_keyvalproperty(key, 1, expiration=expiry)
else:
oldexp = getexpir_keyvalproperty(key) - time.time()
if oldexp <= 0:
delete_keyvalproperty(key)
return self.incr(key, expiry, elastic_expiry)
set_keyvalproperty(key, int(get_keyvalproperty(key))+1, expiration=int(round(oldexp)))
return int(self.get(key))
def get(self, key):
value = get_keyvalproperty(key)
if value:
return int(value)
return 0
def reset(self):
return False

View File

@ -4,7 +4,7 @@ import time
import json import json
from functools import partial from functools import partial
from titanembeds.utils import cache from titanembeds.utils import cache
from redislite import Redis from titanembeds.database import db, KeyValueProperties, get_keyvalproperty, set_keyvalproperty
_DISCORD_API_BASE = "https://discordapp.com/api/v6" _DISCORD_API_BASE = "https://discordapp.com/api/v6"
@ -19,21 +19,21 @@ class DiscordREST:
self.global_redis_prefix = "discordapiratelimit/" self.global_redis_prefix = "discordapiratelimit/"
self.bot_token = bot_token self.bot_token = bot_token
self.user_agent = "TitanEmbeds (https://github.com/EndenDragon/Titan) Python/{} requests/{}".format(sys.version_info, requests.__version__) self.user_agent = "TitanEmbeds (https://github.com/EndenDragon/Titan) Python/{} requests/{}".format(sys.version_info, requests.__version__)
self.rate_limit_bucket = Redis("redislite.db")
if not self._bucket_contains("global_limited"): if not self._bucket_contains("global_limited"):
self._set_bucket("global_limited", False) self._set_bucket("global_limited", False)
self._set_bucket("global_limit_expire", 0) self._set_bucket("global_limit_expire", 0)
def _get_bucket(self, key): def _get_bucket(self, key):
value = self.rate_limit_bucket.get(self.global_redis_prefix + key) value = get_keyvalproperty(self.global_redis_prefix + key)
return value return value
def _set_bucket(self, key, value): def _set_bucket(self, key, value):
return self.rate_limit_bucket.set(self.global_redis_prefix + key, value) #set_keyvalproperty("", "")
return ""#set_keyvalproperty(self.global_redis_prefix + key, value)
def _bucket_contains(self, key): def _bucket_contains(self, key):
return self.rate_limit_bucket.exists(self.global_redis_prefix + key) return ""#ifexists_keyvalproperty(self.global_redis_prefix + key)
def request(self, verb, url, **kwargs): def request(self, verb, url, **kwargs):
headers = { headers = {

View File

@ -1,6 +1,6 @@
from beaker.cache import CacheManager from beaker.cache import CacheManager
from beaker.util import parse_cache_config_options from beaker.util import parse_cache_config_options
from titanembeds.database import db, Guilds from titanembeds.database import db, Guilds, KeyValueProperties
from flask import request, session from flask import request, session
from flask_limiter import Limiter from flask_limiter import Limiter
from config import config from config import config