Update to new worms version.

master
voussoir 2022-07-15 22:12:58 -07:00
parent c9fd6637b3
commit 64ad0ca501
No known key found for this signature in database
GPG Key ID: 5F7554F8C26DACCB
11 changed files with 153 additions and 165 deletions

View File

@ -25,7 +25,7 @@ class BDBFeedMixin:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@worms.transaction @worms.atomic
def add_feed( def add_feed(
self, self,
*, *,
@ -150,7 +150,7 @@ class BDBFeedMixin:
query = 'SELECT * FROM feeds WHERE parent_id IS NULL ORDER BY ui_order_rank ASC' query = 'SELECT * FROM feeds WHERE parent_id IS NULL ORDER BY ui_order_rank ASC'
return self.get_objects_by_sql(objects.Feed, query) return self.get_objects_by_sql(objects.Feed, query)
@worms.transaction @worms.atomic
def reassign_ui_order_ranks(self): def reassign_ui_order_ranks(self):
feeds = list(self.get_root_feeds()) feeds = list(self.get_root_feeds())
rank = 1 rank = 1
@ -165,7 +165,7 @@ class BDBFilterMixin:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@worms.transaction @worms.atomic
def add_filter(self, name, conditions, actions): def add_filter(self, name, conditions, actions):
name = objects.Filter.normalize_name(name) name = objects.Filter.normalize_name(name)
conditions = objects.Filter.normalize_conditions(conditions) conditions = objects.Filter.normalize_conditions(conditions)
@ -198,7 +198,7 @@ class BDBFilterMixin:
def get_filters_by_sql(self, query, bindings=None) -> typing.Iterable[objects.Filter]: def get_filters_by_sql(self, query, bindings=None) -> typing.Iterable[objects.Filter]:
return self.get_objects_by_sql(objects.Filter, query, bindings) return self.get_objects_by_sql(objects.Filter, query, bindings)
@worms.transaction @worms.atomic
def process_news_through_filters(self, news): def process_news_through_filters(self, news):
def prepare_filters(feed): def prepare_filters(feed):
filters = [] filters = []
@ -236,7 +236,7 @@ class BDBNewsMixin:
def __init__(self): def __init__(self):
super().__init__() super().__init__()
@worms.transaction @worms.atomic
def add_news( def add_news(
self, self,
*, *,
@ -550,7 +550,7 @@ class BDBNewsMixin:
if news is not BDBNewsMixin.DUPLICATE_BAIL: if news is not BDBNewsMixin.DUPLICATE_BAIL:
yield news yield news
@worms.transaction @worms.atomic
def ingest_news_xml(self, soup:bs4.BeautifulSoup, feed): def ingest_news_xml(self, soup:bs4.BeautifulSoup, feed):
if soup.rss: if soup.rss:
newss = self._ingest_news_rss(soup, feed) newss = self._ingest_news_rss(soup, feed)
@ -619,7 +619,7 @@ class BringDB(
Compare database's user_version against constants.DATABASE_VERSION, Compare database's user_version against constants.DATABASE_VERSION,
raising exceptions.DatabaseOutOfDate if not correct. raising exceptions.DatabaseOutOfDate if not correct.
''' '''
existing = self.execute('PRAGMA user_version').fetchone()[0] existing = self.pragma_read('user_version')
if existing != constants.DATABASE_VERSION: if existing != constants.DATABASE_VERSION:
raise exceptions.DatabaseOutOfDate( raise exceptions.DatabaseOutOfDate(
existing=existing, existing=existing,
@ -629,8 +629,10 @@ class BringDB(
def _first_time_setup(self): def _first_time_setup(self):
log.info('Running first-time database setup.') log.info('Running first-time database setup.')
self.executescript(constants.DB_INIT) with self.transaction:
self.commit() self._load_pragmas()
self.pragma_write('user_version', constants.DATABASE_VERSION)
self.executescript(constants.DB_INIT)
def _init_caches(self): def _init_caches(self):
self.caches = { self.caches = {
@ -652,21 +654,22 @@ class BringDB(
raise FileNotFoundError(msg) raise FileNotFoundError(msg)
self.data_directory.makedirs(exist_ok=True) self.data_directory.makedirs(exist_ok=True)
log.debug('Connecting to sqlite file "%s".', self.database_filepath.absolute_path) self.sql_read = self._make_sqlite_read_connection(self.database_filepath)
self.sql = sqlite3.connect(self.database_filepath.absolute_path) self.sql_write = self._make_sqlite_write_connection(self.database_filepath)
self.sql.row_factory = sqlite3.Row
if existing_database: if existing_database:
if not skip_version_check: if not skip_version_check:
self._check_version() self._check_version()
self._load_pragmas() with self.transaction:
self._load_pragmas()
else: else:
self._first_time_setup() self._first_time_setup()
def _load_pragmas(self): def _load_pragmas(self):
log.debug('Reloading pragmas.') log.debug('Reloading pragmas.')
self.executescript(constants.DB_PRAGMAS) # 50 MB cache
self.commit() self.pragma_write('cache_size', -50000)
self.pragma_write('foreign_keys', 'on')
@classmethod @classmethod
def closest_bringdb(cls, path='.', *args, **kwargs): def closest_bringdb(cls, path='.', *args, **kwargs):
@ -717,6 +720,5 @@ class BringDB(
while True: while True:
id = RNG.getrandbits(32) id = RNG.getrandbits(32)
exists = self.select_one(f'SELECT 1 FROM {table} WHERE id == ?', [id]) if not self.exists(f'SELECT 1 FROM {table} WHERE id == ?', [id]):
if not exists:
return id return id

View File

@ -3,21 +3,8 @@ import requests
from voussoirkit import sqlhelpers from voussoirkit import sqlhelpers
DATABASE_VERSION = 1 DATABASE_VERSION = 1
DB_VERSION_PRAGMA = f'''
PRAGMA user_version = {DATABASE_VERSION};
'''
DB_PRAGMAS = f'''
-- 50 MB cache
PRAGMA cache_size = -50000;
PRAGMA foreign_keys = ON;
'''
DB_INIT = f''' DB_INIT = f'''
BEGIN;
{DB_PRAGMAS}
{DB_VERSION_PRAGMA}
----------------------------------------------------------------------------------------------------
CREATE TABLE IF NOT EXISTS feeds( CREATE TABLE IF NOT EXISTS feeds(
id INT PRIMARY KEY NOT NULL, id INT PRIMARY KEY NOT NULL,
parent_id INT, parent_id INT,
@ -100,8 +87,6 @@ CREATE TABLE IF NOT EXISTS feed_filter_rel(
FOREIGN KEY(filter_id) REFERENCES filters(id), FOREIGN KEY(filter_id) REFERENCES filters(id),
PRIMARY KEY(feed_id, filter_id) PRIMARY KEY(feed_id, filter_id)
); );
----------------------------------------------------------------------------------------------------
COMMIT;
''' '''
SQL_COLUMNS = sqlhelpers.extract_table_column_map(DB_INIT) SQL_COLUMNS = sqlhelpers.extract_table_column_map(DB_INIT)
SQL_INDEX = sqlhelpers.reverse_table_column_map(SQL_COLUMNS) SQL_INDEX = sqlhelpers.reverse_table_column_map(SQL_COLUMNS)

View File

@ -171,7 +171,7 @@ class Feed(ObjectBase):
normalize_web_url = helpers.normalize_string_blank_to_none normalize_web_url = helpers.normalize_string_blank_to_none
@worms.transaction @worms.atomic
def clear_last_refresh_error(self): def clear_last_refresh_error(self):
if self.last_refresh_error is None: if self.last_refresh_error is None:
return return
@ -183,7 +183,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.last_refresh_error = None self.last_refresh_error = None
@worms.transaction @worms.atomic
def delete(self): def delete(self):
self.assert_not_deleted() self.assert_not_deleted()
@ -375,7 +375,7 @@ class Feed(ObjectBase):
if web_url: if web_url:
self.set_web_url(web_url) self.set_web_url(web_url)
@worms.transaction @worms.atomic
def _refresh(self): def _refresh(self):
soup = helpers.fetch_xml_cached(self.rss_url, headers=self.http_headers) soup = helpers.fetch_xml_cached(self.rss_url, headers=self.http_headers)
@ -397,7 +397,7 @@ class Feed(ObjectBase):
} }
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
@worms.transaction @worms.atomic
def refresh(self): def refresh(self):
if not self.rss_url: if not self.rss_url:
self.clear_last_refresh_error() self.clear_last_refresh_error()
@ -424,7 +424,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
return ret return ret
@worms.transaction @worms.atomic
def refresh_all(self): def refresh_all(self):
''' '''
Refresh this feed and all of its descendants, except the ones with Refresh this feed and all of its descendants, except the ones with
@ -441,7 +441,7 @@ class Feed(ObjectBase):
except Exception: except Exception:
log.warning(traceback.format_exc()) log.warning(traceback.format_exc())
@worms.transaction @worms.atomic
def set_autorefresh_interval(self, autorefresh_interval): def set_autorefresh_interval(self, autorefresh_interval):
self.assert_not_deleted() self.assert_not_deleted()
autorefresh_interval = self.normalize_autorefresh_interval(autorefresh_interval) autorefresh_interval = self.normalize_autorefresh_interval(autorefresh_interval)
@ -453,7 +453,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.autorefresh_interval = autorefresh_interval self.autorefresh_interval = autorefresh_interval
@worms.transaction @worms.atomic
def set_description(self, description): def set_description(self, description):
self.assert_not_deleted() self.assert_not_deleted()
description = self.normalize_description(description) description = self.normalize_description(description)
@ -479,7 +479,7 @@ class Feed(ObjectBase):
except Exception: except Exception:
log.warning(traceback.format_exc()) log.warning(traceback.format_exc())
@worms.transaction @worms.atomic
def set_filters(self, filters): def set_filters(self, filters):
self.assert_not_deleted() self.assert_not_deleted()
@ -504,7 +504,7 @@ class Feed(ObjectBase):
} }
self.bringdb.insert(table='feed_filter_rel', data=data) self.bringdb.insert(table='feed_filter_rel', data=data)
@worms.transaction @worms.atomic
def set_http_headers(self, http_headers): def set_http_headers(self, http_headers):
self.assert_not_deleted() self.assert_not_deleted()
http_headers = self.normalize_http_headers(http_headers) http_headers = self.normalize_http_headers(http_headers)
@ -516,7 +516,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.http_headers = http_headers self.http_headers = http_headers
@worms.transaction @worms.atomic
def set_icon(self, icon:bytes): def set_icon(self, icon:bytes):
self.assert_not_deleted() self.assert_not_deleted()
icon = self.normalize_icon(icon) icon = self.normalize_icon(icon)
@ -528,7 +528,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.icon = icon self.icon = icon
@worms.transaction @worms.atomic
def set_isolate_guids(self, isolate_guids): def set_isolate_guids(self, isolate_guids):
self.assert_not_deleted() self.assert_not_deleted()
isolate_guids = self.normalize_isolate_guids(isolate_guids) isolate_guids = self.normalize_isolate_guids(isolate_guids)
@ -550,7 +550,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=News, pairs=pairs, where_key='original_feed_id') self.bringdb.update(table=News, pairs=pairs, where_key='original_feed_id')
self.isolate_guids = isolate_guids self.isolate_guids = isolate_guids
@worms.transaction @worms.atomic
def set_parent(self, parent, ui_order_rank=None): def set_parent(self, parent, ui_order_rank=None):
self.assert_not_deleted() self.assert_not_deleted()
if parent is None: if parent is None:
@ -586,7 +586,7 @@ class Feed(ObjectBase):
if parent is not None: if parent is not None:
self._parent = parent self._parent = parent
@worms.transaction @worms.atomic
def set_refresh_with_others(self, refresh_with_others): def set_refresh_with_others(self, refresh_with_others):
self.assert_not_deleted() self.assert_not_deleted()
refresh_with_others = self.normalize_refresh_with_others(refresh_with_others) refresh_with_others = self.normalize_refresh_with_others(refresh_with_others)
@ -598,7 +598,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.refresh_with_others = refresh_with_others self.refresh_with_others = refresh_with_others
@worms.transaction @worms.atomic
def set_rss_url(self, rss_url): def set_rss_url(self, rss_url):
self.assert_not_deleted() self.assert_not_deleted()
rss_url = self.normalize_rss_url(rss_url) rss_url = self.normalize_rss_url(rss_url)
@ -610,7 +610,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.rss_url = rss_url self.rss_url = rss_url
@worms.transaction @worms.atomic
def set_title(self, title): def set_title(self, title):
self.assert_not_deleted() self.assert_not_deleted()
title = self.normalize_title(title) title = self.normalize_title(title)
@ -622,7 +622,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.title = title self.title = title
@worms.transaction @worms.atomic
def set_ui_order_rank(self, ui_order_rank): def set_ui_order_rank(self, ui_order_rank):
self.assert_not_deleted() self.assert_not_deleted()
ui_order_rank = self.normalize_ui_order_rank(ui_order_rank) ui_order_rank = self.normalize_ui_order_rank(ui_order_rank)
@ -634,7 +634,7 @@ class Feed(ObjectBase):
self.bringdb.update(table=Feed, pairs=pairs, where_key='id') self.bringdb.update(table=Feed, pairs=pairs, where_key='id')
self.ui_order_rank = ui_order_rank self.ui_order_rank = ui_order_rank
@worms.transaction @worms.atomic
def set_web_url(self, web_url): def set_web_url(self, web_url):
self.assert_not_deleted() self.assert_not_deleted()
web_url = self.normalize_web_url(web_url) web_url = self.normalize_web_url(web_url)
@ -1044,7 +1044,7 @@ class Filter(ObjectBase):
## ##
@worms.transaction @worms.atomic
def delete(self): def delete(self):
self.assert_not_deleted() self.assert_not_deleted()
@ -1118,7 +1118,7 @@ class Filter(ObjectBase):
conditions.map(lambda token: Filter._parse_stored_condition(token, run_validator=run_validator)) conditions.map(lambda token: Filter._parse_stored_condition(token, run_validator=run_validator))
return conditions return conditions
@worms.transaction @worms.atomic
def process_news(self, news): def process_news(self, news):
# Because we called self.conditions.map(parse_stored_condition), all of # Because we called self.conditions.map(parse_stored_condition), all of
# the tokens inside the ExpressionTree are now partialed functions that # the tokens inside the ExpressionTree are now partialed functions that
@ -1143,7 +1143,7 @@ class Filter(ObjectBase):
return Filter.THEN_CONTINUE_FILTERS return Filter.THEN_CONTINUE_FILTERS
@worms.transaction @worms.atomic
def set_actions(self, actions:str): def set_actions(self, actions:str):
self.assert_not_deleted() self.assert_not_deleted()
actions = self.normalize_actions(actions) actions = self.normalize_actions(actions)
@ -1157,7 +1157,7 @@ class Filter(ObjectBase):
self._actions = actions self._actions = actions
self.actions = self.parse_actions(actions) self.actions = self.parse_actions(actions)
@worms.transaction @worms.atomic
def set_conditions(self, conditions:str): def set_conditions(self, conditions:str):
self.assert_not_deleted() self.assert_not_deleted()
# Note that the database is given the input string, not the normalize # Note that the database is given the input string, not the normalize
@ -1172,7 +1172,7 @@ class Filter(ObjectBase):
self._conditions = conditions self._conditions = conditions
self.conditions = self.parse_conditions(conditions) self.conditions = self.parse_conditions(conditions)
@worms.transaction @worms.atomic
def set_name(self, name): def set_name(self, name):
self.assert_not_deleted() self.assert_not_deleted()
name = self.normalize_name(name) name = self.normalize_name(name)
@ -1371,7 +1371,7 @@ class News(ObjectBase):
return j return j
@worms.transaction @worms.atomic
def move_to_feed(self, feed): def move_to_feed(self, feed):
self.assert_not_deleted() self.assert_not_deleted()
@ -1407,7 +1407,7 @@ class News(ObjectBase):
published = published.strftime('%Y-%m-%d %H:%M') published = published.strftime('%Y-%m-%d %H:%M')
return published return published
@worms.transaction @worms.atomic
def set_read(self, read): def set_read(self, read):
self.assert_not_deleted() self.assert_not_deleted()
read = self.normalize_read(read) read = self.normalize_read(read)
@ -1419,7 +1419,7 @@ class News(ObjectBase):
self.bringdb.update(table=News, pairs=pairs, where_key='id') self.bringdb.update(table=News, pairs=pairs, where_key='id')
self.read = read self.read = read
@worms.transaction @worms.atomic
def set_recycled(self, recycled): def set_recycled(self, recycled):
self.assert_not_deleted() self.assert_not_deleted()
recycled = self.normalize_recycled(recycled) recycled = self.normalize_recycled(recycled)

View File

@ -22,30 +22,29 @@ def load_bringdb():
def init_argparse(args): def init_argparse(args):
bringdb = bringrss.bringdb.BringDB(create=True) bringdb = bringrss.bringdb.BringDB(create=True)
bringdb.commit()
return 0 return 0
def refresh_argparse(args): def refresh_argparse(args):
load_bringdb() load_bringdb()
now = bringrss.helpers.now() now = bringrss.helpers.now()
soonest = float('inf') soonest = float('inf')
for feed in list(bringdb.get_feeds()): with bringdb.transaction:
next_refresh = feed.next_refresh for feed in list(bringdb.get_feeds()):
if now > next_refresh: next_refresh = feed.next_refresh
feed.refresh() if now > next_refresh:
elif next_refresh < soonest: feed.refresh()
soonest = next_refresh elif next_refresh < soonest:
soonest = next_refresh
if soonest != float('inf'): if soonest != float('inf'):
soonest = hms.seconds_to_hms_letters(soonest - now) soonest = hms.seconds_to_hms_letters(soonest - now)
pipeable.stderr(f'The next soonest is in {soonest}.') pipeable.stderr(f'The next soonest is in {soonest}.')
bringdb.commit()
return 0 return 0
def refresh_all_argparse(args): def refresh_all_argparse(args):
load_bringdb() load_bringdb()
for feed in list(bringdb.get_feeds()): with bringdb.transaction:
feed.refresh() for feed in list(bringdb.get_feeds()):
bringdb.commit() feed.refresh()
@operatornotify.main_decorator(subject='bringrss_cli') @operatornotify.main_decorator(subject='bringrss_cli')
@vlogging.main_decorator @vlogging.main_decorator

View File

@ -251,7 +251,6 @@ def refresh_queue_thread():
feed.refresh() feed.refresh()
except Exception as exc: except Exception as exc:
log.warning('Refreshing %s encountered:\n%s', feed, traceback.format_exc()) log.warning('Refreshing %s encountered:\n%s', feed, traceback.format_exc())
bringdb.commit()
flasktools.send_sse( flasktools.send_sse(
event='feed_refresh_finished', event='feed_refresh_finished',
data=json.dumps(feed.jsonify(unread_count=True)), data=json.dumps(feed.jsonify(unread_count=True)),
@ -262,7 +261,8 @@ def refresh_queue_thread():
feed = REFRESH_QUEUE.get() feed = REFRESH_QUEUE.get()
if feed is QUIT_EVENT: if feed is QUIT_EVENT:
break break
_refresh_one(feed) with bringdb.transaction:
_refresh_one(feed)
_REFRESH_QUEUE_SET.discard(feed) _REFRESH_QUEUE_SET.discard(feed)
if REFRESH_QUEUE.empty(): if REFRESH_QUEUE.empty():
flasktools.send_sse(event='feed_refresh_queue_finished', data='') flasktools.send_sse(event='feed_refresh_queue_finished', data='')

View File

@ -34,7 +34,8 @@ def post_feeds_add():
title = request.form.get('title') title = request.form.get('title')
isolate_guids = request.form.get('isolate_guids', False) isolate_guids = request.form.get('isolate_guids', False)
isolate_guids = stringtools.truthystring(isolate_guids) isolate_guids = stringtools.truthystring(isolate_guids)
feed = common.bringdb.add_feed(rss_url=rss_url, title=title, isolate_guids=isolate_guids) with common.bringdb.transaction:
feed = common.bringdb.add_feed(rss_url=rss_url, title=title, isolate_guids=isolate_guids)
# We want to refresh the feed now and not just put it on the refresh queue, # We want to refresh the feed now and not just put it on the refresh queue,
# because when the user gets the response to this endpoint they will # because when the user gets the response to this endpoint they will
@ -44,12 +45,11 @@ def post_feeds_add():
# ux. However, we need to commit first, because if the refresh fails we want # ux. However, we need to commit first, because if the refresh fails we want
# the user to be able to see the Feed in the ui and read its # the user to be able to see the Feed in the ui and read its
# last_refresh_error message. # last_refresh_error message.
common.bringdb.commit() with common.bringdb.transaction:
try: try:
feed.refresh() feed.refresh()
common.bringdb.commit() except Exception:
except Exception: log.warning('Refreshing %s raised:\n%s', feed, traceback.format_exc())
log.warning('Refreshing %s raised:\n%s', feed, traceback.format_exc())
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@ -73,9 +73,9 @@ def get_feed_json(feed_id):
@site.route('/feed/<feed_id>/delete', methods=['POST']) @site.route('/feed/<feed_id>/delete', methods=['POST'])
def post_feed_delete(feed_id): def post_feed_delete(feed_id):
feed = common.get_feed(feed_id, response_type='json') with common.bringdb.transaction:
feed.delete() feed = common.get_feed(feed_id, response_type='json')
common.bringdb.commit() feed.delete()
return flasktools.json_response({}) return flasktools.json_response({})
@site.route('/feed/<feed_id>/icon.png') @site.route('/feed/<feed_id>/icon.png')
@ -122,16 +122,16 @@ def get_feed_settings(feed_id):
@site.route('/feed/<feed_id>/set_autorefresh_interval', methods=['POST']) @site.route('/feed/<feed_id>/set_autorefresh_interval', methods=['POST'])
@flasktools.required_fields(['autorefresh_interval']) @flasktools.required_fields(['autorefresh_interval'])
def post_feed_set_autorefresh_interval(feed_id): def post_feed_set_autorefresh_interval(feed_id):
feed = common.get_feed(feed_id, response_type='json')
autorefresh_interval = request.form['autorefresh_interval'] autorefresh_interval = request.form['autorefresh_interval']
try: try:
autorefresh_interval = int(autorefresh_interval) autorefresh_interval = int(autorefresh_interval)
except ValueError: except ValueError:
return flasktools.json_response({}, status=400) return flasktools.json_response({}, status=400)
feed = common.get_feed(feed_id, response_type='json')
if autorefresh_interval != feed.autorefresh_interval: if autorefresh_interval != feed.autorefresh_interval:
feed.set_autorefresh_interval(autorefresh_interval) with common.bringdb.transaction:
common.bringdb.commit() feed.set_autorefresh_interval(autorefresh_interval)
# Wake up the autorefresh thread so it can recalculate its schedule. # Wake up the autorefresh thread so it can recalculate its schedule.
common.AUTOREFRESH_THREAD_EVENTS.put("wake up!") common.AUTOREFRESH_THREAD_EVENTS.put("wake up!")
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@ -139,42 +139,42 @@ def post_feed_set_autorefresh_interval(feed_id):
@site.route('/feed/<feed_id>/set_filters', methods=['POST']) @site.route('/feed/<feed_id>/set_filters', methods=['POST'])
@flasktools.required_fields(['filter_ids']) @flasktools.required_fields(['filter_ids'])
def post_feed_set_filters(feed_id): def post_feed_set_filters(feed_id):
feed = common.get_feed(feed_id, response_type='json')
filter_ids = stringtools.comma_space_split(request.form['filter_ids']) filter_ids = stringtools.comma_space_split(request.form['filter_ids'])
filters = [common.get_filter(id, response_type='json') for id in filter_ids] with common.bringdb.transaction:
feed.set_filters(filters) feed = common.get_feed(feed_id, response_type='json')
common.bringdb.commit() filters = [common.get_filter(id, response_type='json') for id in filter_ids]
feed.set_filters(filters)
return flasktools.json_response(feed.jsonify(filters=True)) return flasktools.json_response(feed.jsonify(filters=True))
@site.route('/feed/<feed_id>/set_http_headers', methods=['POST']) @site.route('/feed/<feed_id>/set_http_headers', methods=['POST'])
@flasktools.required_fields(['http_headers']) @flasktools.required_fields(['http_headers'])
def post_feed_set_http_headers(feed_id): def post_feed_set_http_headers(feed_id):
feed = common.get_feed(feed_id, response_type='json') with common.bringdb.transaction:
feed.set_http_headers(request.form['http_headers']) feed = common.get_feed(feed_id, response_type='json')
common.bringdb.commit() feed.set_http_headers(request.form['http_headers'])
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_icon', methods=['POST']) @site.route('/feed/<feed_id>/set_icon', methods=['POST'])
@flasktools.required_fields(['image_base64']) @flasktools.required_fields(['image_base64'])
def post_feed_set_icon(feed_id): def post_feed_set_icon(feed_id):
feed = common.get_feed(feed_id, response_type='json')
image_base64 = request.form['image_base64'] image_base64 = request.form['image_base64']
image_base64 = image_base64.split(';base64,')[-1] image_base64 = image_base64.split(';base64,')[-1]
image_binary = base64.b64decode(image_base64) image_binary = base64.b64decode(image_base64)
feed.set_icon(image_binary) with common.bringdb.transaction:
common.bringdb.commit() feed = common.get_feed(feed_id, response_type='json')
feed.set_icon(image_binary)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_isolate_guids', methods=['POST']) @site.route('/feed/<feed_id>/set_isolate_guids', methods=['POST'])
@flasktools.required_fields(['isolate_guids']) @flasktools.required_fields(['isolate_guids'])
def post_feed_set_isolate_guids(feed_id): def post_feed_set_isolate_guids(feed_id):
feed = common.get_feed(feed_id, response_type='json')
try: try:
isolate_guids = stringtools.truthystring(request.form['isolate_guids']) isolate_guids = stringtools.truthystring(request.form['isolate_guids'])
except ValueError: except ValueError:
return flasktools.json_response({}, status=400) return flasktools.json_response({}, status=400)
feed.set_isolate_guids(isolate_guids) with common.bringdb.transaction:
common.bringdb.commit() feed = common.get_feed(feed_id, response_type='json')
feed.set_isolate_guids(isolate_guids)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_parent', methods=['POST']) @site.route('/feed/<feed_id>/set_parent', methods=['POST'])
@ -193,8 +193,8 @@ def post_feed_set_parent(feed_id):
ui_order_rank = float(ui_order_rank) ui_order_rank = float(ui_order_rank)
if parent != feed.parent or ui_order_rank != feed.ui_order_rank: if parent != feed.parent or ui_order_rank != feed.ui_order_rank:
feed.set_parent(parent, ui_order_rank=ui_order_rank) with common.bringdb.transaction:
common.bringdb.commit() feed.set_parent(parent, ui_order_rank=ui_order_rank)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@ -204,8 +204,8 @@ def post_feed_set_refresh_with_others(feed_id):
feed = common.get_feed(feed_id, response_type='json') feed = common.get_feed(feed_id, response_type='json')
refresh_with_others = stringtools.truthystring(request.form['refresh_with_others']) refresh_with_others = stringtools.truthystring(request.form['refresh_with_others'])
if refresh_with_others != feed.refresh_with_others: if refresh_with_others != feed.refresh_with_others:
feed.set_refresh_with_others(refresh_with_others) with common.bringdb.transaction:
common.bringdb.commit() feed.set_refresh_with_others(refresh_with_others)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_rss_url', methods=['POST']) @site.route('/feed/<feed_id>/set_rss_url', methods=['POST'])
@ -214,8 +214,8 @@ def post_feed_set_rss_url(feed_id):
feed = common.get_feed(feed_id, response_type='json') feed = common.get_feed(feed_id, response_type='json')
rss_url = request.form['rss_url'] rss_url = request.form['rss_url']
if rss_url != feed.rss_url: if rss_url != feed.rss_url:
feed.set_rss_url(rss_url) with common.bringdb.transaction:
common.bringdb.commit() feed.set_rss_url(rss_url)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_web_url', methods=['POST']) @site.route('/feed/<feed_id>/set_web_url', methods=['POST'])
@ -224,8 +224,8 @@ def post_feed_set_web_url(feed_id):
feed = common.get_feed(feed_id, response_type='json') feed = common.get_feed(feed_id, response_type='json')
web_url = request.form['web_url'] web_url = request.form['web_url']
if web_url != feed.web_url: if web_url != feed.web_url:
feed.set_web_url(web_url) with common.bringdb.transaction:
common.bringdb.commit() feed.set_web_url(web_url)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_title', methods=['POST']) @site.route('/feed/<feed_id>/set_title', methods=['POST'])
@ -234,8 +234,8 @@ def post_feed_set_title(feed_id):
feed = common.get_feed(feed_id, response_type='json') feed = common.get_feed(feed_id, response_type='json')
title = request.form['title'] title = request.form['title']
if title != feed.title: if title != feed.title:
feed.set_title(title) with common.bringdb.transaction:
common.bringdb.commit() feed.set_title(title)
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())
@site.route('/feed/<feed_id>/set_ui_order_rank', methods=['POST']) @site.route('/feed/<feed_id>/set_ui_order_rank', methods=['POST'])
@ -244,7 +244,7 @@ def post_feed_set_ui_order_rank(feed_id):
feed = common.get_feed(feed_id, response_type='json') feed = common.get_feed(feed_id, response_type='json')
ui_order_rank = float(request.form['ui_order_rank']) ui_order_rank = float(request.form['ui_order_rank'])
if ui_order_rank != feed.ui_order_rank: if ui_order_rank != feed.ui_order_rank:
feed.set_ui_order_rank(ui_order_rank) with common.bringdb.transaction:
common.bringdb.reassign_ui_order_rank() feed.set_ui_order_rank(ui_order_rank)
common.bringdb.commit() common.bringdb.reassign_ui_order_rank()
return flasktools.json_response(feed.jsonify()) return flasktools.json_response(feed.jsonify())

View File

@ -36,8 +36,8 @@ def post_filters_add():
name = request.form.get('name', None) name = request.form.get('name', None)
conditions = request.form['conditions'] conditions = request.form['conditions']
actions = request.form['actions'] actions = request.form['actions']
filt = common.bringdb.add_filter(name=name, conditions=conditions, actions=actions) with common.bringdb.transaction:
common.bringdb.commit() filt = common.bringdb.add_filter(name=name, conditions=conditions, actions=actions)
flasktools.send_sse(event='filters_changed', data=None) flasktools.send_sse(event='filters_changed', data=None)
return flasktools.json_response(filt.jsonify()) return flasktools.json_response(filt.jsonify())
@ -61,11 +61,11 @@ def get_filter_json(filter_id):
@site.route('/filter/<filter_id>/delete', methods=['POST']) @site.route('/filter/<filter_id>/delete', methods=['POST'])
def post_filter_delete(filter_id): def post_filter_delete(filter_id):
filt = common.get_filter(filter_id, response_type='json') filt = common.get_filter(filter_id, response_type='json')
try: with common.bringdb.transaction:
filt.delete() try:
except bringrss.exceptions.FilterStillInUse as exc: filt.delete()
return flasktools.json_response(exc.jsonify(), status=400) except bringrss.exceptions.FilterStillInUse as exc:
common.bringdb.commit() return flasktools.json_response(exc.jsonify(), status=400)
flasktools.send_sse(event='filters_changed', data=None) flasktools.send_sse(event='filters_changed', data=None)
return flasktools.json_response({}) return flasktools.json_response({})
@ -77,16 +77,16 @@ def post_run_filter_now(filter_id):
else: else:
feed = None feed = None
filt = common.get_filter(filter_id, response_type='json') with common.bringdb.transaction:
newss = list(common.bringdb.get_newss( filt = common.get_filter(filter_id, response_type='json')
feed=feed, newss = list(common.bringdb.get_newss(
read=None, feed=feed,
recycled=None, read=None,
)) recycled=None,
for news in newss: ))
filt.process_news(news) for news in newss:
filt.process_news(news)
common.bringdb.commit()
return flasktools.json_response({}) return flasktools.json_response({})
@site.route('/filter/<filter_id>/set_actions', methods=['POST']) @site.route('/filter/<filter_id>/set_actions', methods=['POST'])
@ -95,8 +95,8 @@ def post_filter_set_actions(filter_id):
filt = common.get_filter(filter_id, response_type='json') filt = common.get_filter(filter_id, response_type='json')
actions = request.form['actions'] actions = request.form['actions']
if actions != filt.actions: if actions != filt.actions:
filt.set_actions(actions) with common.bringdb.transaction:
common.bringdb.commit() filt.set_actions(actions)
return flasktools.json_response(filt.jsonify()) return flasktools.json_response(filt.jsonify())
@site.route('/filter/<filter_id>/set_conditions', methods=['POST']) @site.route('/filter/<filter_id>/set_conditions', methods=['POST'])
@ -105,8 +105,8 @@ def post_filter_set_conditions(filter_id):
filt = common.get_filter(filter_id, response_type='json') filt = common.get_filter(filter_id, response_type='json')
conditions = request.form['conditions'] conditions = request.form['conditions']
if conditions != filt.conditions: if conditions != filt.conditions:
filt.set_conditions(conditions) with common.bringdb.transaction:
common.bringdb.commit() filt.set_conditions(conditions)
return flasktools.json_response(filt.jsonify()) return flasktools.json_response(filt.jsonify())
@site.route('/filter/<filter_id>/set_name', methods=['POST']) @site.route('/filter/<filter_id>/set_name', methods=['POST'])
@ -115,25 +115,26 @@ def post_filter_set_name(filter_id):
filt = common.get_filter(filter_id, response_type='json') filt = common.get_filter(filter_id, response_type='json')
name = request.form['name'] name = request.form['name']
if name != filt.name: if name != filt.name:
filt.set_name(name) with common.bringdb.transaction:
common.bringdb.commit() filt.set_name(name)
return flasktools.json_response(filt.jsonify()) return flasktools.json_response(filt.jsonify())
@site.route('/filter/<filter_id>/update', methods=['POST']) @site.route('/filter/<filter_id>/update', methods=['POST'])
def post_filter_update(filter_id): def post_filter_update(filter_id):
filt = common.get_filter(filter_id, response_type='json') filt = common.get_filter(filter_id, response_type='json')
name = request.form.get('name', None) name = request.form.get('name', None)
if name is not None:
filt.set_name(name)
conditions = request.form.get('conditions', None) with common.bringdb.transaction:
if conditions is not None: if name is not None:
filt.set_conditions(conditions) filt.set_name(name)
actions = request.form.get('actions', None) conditions = request.form.get('conditions', None)
if actions is not None: if conditions is not None:
filt.set_actions(actions) filt.set_conditions(conditions)
actions = request.form.get('actions', None)
if actions is not None:
filt.set_actions(actions)
common.bringdb.commit()
flasktools.send_sse(event='filters_changed', data=None) flasktools.send_sse(event='filters_changed', data=None)
return flasktools.json_response(filt.jsonify()) return flasktools.json_response(filt.jsonify())

View File

@ -16,9 +16,8 @@ site = common.site
def post_news_set_read(news_id): def post_news_set_read(news_id):
news = common.get_news(news_id, response_type='json') news = common.get_news(news_id, response_type='json')
read = stringtools.truthystring(request.form['read']) read = stringtools.truthystring(request.form['read'])
news.set_read(read) with common.bringdb.transaction:
news.set_read(read)
common.bringdb.commit()
return flasktools.json_response(news.jsonify()) return flasktools.json_response(news.jsonify())
@site.route('/news/<news_id>/set_recycled', methods=['POST']) @site.route('/news/<news_id>/set_recycled', methods=['POST'])
@ -26,9 +25,8 @@ def post_news_set_read(news_id):
def post_news_set_recycled(news_id): def post_news_set_recycled(news_id):
news = common.get_news(news_id, response_type='json') news = common.get_news(news_id, response_type='json')
recycled = stringtools.truthystring(request.form['recycled']) recycled = stringtools.truthystring(request.form['recycled'])
news.set_recycled(recycled) with common.bringdb.transaction:
news.set_recycled(recycled)
common.bringdb.commit()
return flasktools.json_response(news.jsonify()) return flasktools.json_response(news.jsonify())
@site.route('/news/<news_id>.json', methods=['GET']) @site.route('/news/<news_id>.json', methods=['GET'])
@ -42,8 +40,8 @@ def post_get_news(news_id):
mark_read = request.form.get('set_read', None) mark_read = request.form.get('set_read', None)
mark_read = stringtools.truthystring(mark_read) mark_read = stringtools.truthystring(mark_read)
if mark_read is not None: if mark_read is not None:
news.set_read(mark_read) with common.bringdb.transaction:
common.bringdb.commit() news.set_read(mark_read)
return flasktools.json_response(news.jsonify(complete=True)) return flasktools.json_response(news.jsonify(complete=True))
@site.route('/batch/news/set_read', methods=['POST']) @site.route('/batch/news/set_read', methods=['POST'])
@ -57,11 +55,11 @@ def post_batch_set_read():
read = stringtools.truthystring(request.form['read']) read = stringtools.truthystring(request.form['read'])
return_ids = [] return_ids = []
for news in newss: with common.bringdb.transaction:
news.set_read(read) for news in newss:
return_ids.append(news.id) news.set_read(read)
return_ids.append(news.id)
common.bringdb.commit()
return flasktools.json_response(return_ids) return flasktools.json_response(return_ids)
@site.route('/batch/news/set_recycled', methods=['POST']) @site.route('/batch/news/set_recycled', methods=['POST'])
@ -75,9 +73,9 @@ def post_batch_recycle_news():
recycled = stringtools.truthystring(request.form['recycled']) recycled = stringtools.truthystring(request.form['recycled'])
return_ids = [] return_ids = []
for news in newss: with common.bringdb.transaction:
news.set_recycled(recycled) for news in newss:
return_ids.append(news.id) news.set_recycled(recycled)
return_ids.append(news.id)
common.bringdb.commit()
return flasktools.json_response(return_ids) return flasktools.json_response(return_ids)

View File

@ -60,7 +60,7 @@ def bringrss_flask_dev(
site.demo_mode = True site.demo_mode = True
if init: if init:
bringrss.bringdb.BringDB(create=True).commit() bringrss.bringdb.BringDB(create=True)
try: try:
backend.common.init_bringdb() backend.common.init_bringdb()

View File

@ -20,8 +20,8 @@ def bringrepl_argparse(args):
return 1 return 1
if args.exec_statement: if args.exec_statement:
exec(args.exec_statement) with B.transaction():
B.commit() exec(args.exec_statement)
else: else:
while True: while True:
try: try:

View File

@ -16,11 +16,11 @@ import bringrss
log = vlogging.getLogger(__name__, 'import_quiterss') log = vlogging.getLogger(__name__, 'import_quiterss')
def import_quiterss_argparse(args): def import_quiterss_argparse(args):
bringdb = bringrss.bringdb.BringDB.closest_bringdb()
if not os.path.isfile(args.feedsdb): if not os.path.isfile(args.feedsdb):
pipeable.stderr(f'{args.bringdb} is not a file.') pipeable.stderr(f'{args.feedsdb} is not a file.')
return 1 return 1
bringdb = bringrss.bringdb.BringDB.closest_bringdb()
message = textwrap.dedent(''' message = textwrap.dedent('''
You should make a backup of your BringRSS database before doing this. You should make a backup of your BringRSS database before doing this.
Do not perform this import more than once. We will not search for duplicate data. Do not perform this import more than once. We will not search for duplicate data.
@ -35,7 +35,13 @@ def import_quiterss_argparse(args):
if not interactive.getpermission('Are you ready?'): if not interactive.getpermission('Are you ready?'):
return 1 return 1
quite_sql = sqlite3.connect(args.feedsdb) with bringdb.transaction:
import_quiterss(feedsdb, bringdb)
return 0
def import_quiterss(feedsdb, bringdb):
quite_sql = sqlite3.connect(feedsdb)
quite_sql.row_factory = sqlite3.Row quite_sql.row_factory = sqlite3.Row
feed_id_map = {} feed_id_map = {}
query = ''' query = '''
@ -171,9 +177,6 @@ def import_quiterss_argparse(args):
) )
if quite_read > 0: if quite_read > 0:
news.set_read(True) news.set_read(True)
bringdb.commit()
return 0
@vlogging.main_decorator @vlogging.main_decorator
def main(argv): def main(argv):