sublime-wakatime/packages/wakatime/offlinequeue.py

134 lines
3.4 KiB
Python
Raw Normal View History

# -*- coding: utf-8 -*-
"""
2015-05-13 01:03:23 +03:00
wakatime.offlinequeue
~~~~~~~~~~~~~~~~~~~~~
2015-05-13 01:03:23 +03:00
Queue for saving heartbeats while offline.
:copyright: (c) 2014 Alan Hamlett.
:license: BSD, see LICENSE for more details.
"""
import logging
import os
from time import sleep
2017-11-09 10:12:05 +03:00
from .compat import json
2018-09-21 08:29:34 +03:00
from .constants import DEFAULT_SYNC_OFFLINE_ACTIVITY, HEARTBEATS_PER_REQUEST
2017-11-09 10:12:05 +03:00
from .heartbeat import Heartbeat
2014-06-10 00:18:30 +04:00
try:
import sqlite3
HAS_SQL = True
2015-09-29 13:11:25 +03:00
except ImportError: # pragma: nocover
2014-06-10 00:18:30 +04:00
HAS_SQL = False
log = logging.getLogger('WakaTime')
class Queue(object):
2017-10-29 21:32:03 +03:00
db_file = '.wakatime.db'
2017-11-09 10:12:05 +03:00
table_name = 'heartbeat_2'
2015-09-29 13:11:25 +03:00
2017-11-09 10:12:05 +03:00
args = None
configs = None
def __init__(self, args, configs):
self.args = args
self.configs = configs
def connect(self):
2017-11-09 10:12:05 +03:00
conn = sqlite3.connect(self._get_db_file(), isolation_level=None)
c = conn.cursor()
2015-09-29 13:11:25 +03:00
c.execute('''CREATE TABLE IF NOT EXISTS {0} (
2017-11-09 10:12:05 +03:00
id text,
heartbeat text)
2015-09-29 13:11:25 +03:00
'''.format(self.table_name))
return (conn, c)
2017-11-09 10:12:05 +03:00
def push(self, heartbeat):
if not HAS_SQL:
2014-06-10 00:18:30 +04:00
return
2014-05-27 01:06:36 +04:00
try:
conn, c = self.connect()
2017-11-09 10:12:05 +03:00
data = {
'id': heartbeat.get_id(),
'heartbeat': heartbeat.json(),
2014-05-27 01:06:36 +04:00
}
2017-11-09 10:12:05 +03:00
c.execute('INSERT INTO {0} VALUES (:id,:heartbeat)'.format(self.table_name), data)
2014-05-27 01:06:36 +04:00
conn.commit()
2014-06-10 00:18:30 +04:00
except sqlite3.Error:
2016-06-17 11:17:29 +03:00
log.traceback()
2019-11-24 18:46:13 +03:00
try:
conn.close()
except: # pragma: nocover
pass
def pop(self):
2017-11-09 10:12:05 +03:00
if not HAS_SQL:
2014-06-10 00:18:30 +04:00
return None
tries = 3
wait = 0.1
2014-05-27 01:06:36 +04:00
try:
conn, c = self.connect()
2014-06-10 00:18:30 +04:00
except sqlite3.Error:
2016-09-02 11:50:54 +03:00
log.traceback(logging.DEBUG)
2014-05-27 01:06:36 +04:00
return None
2017-11-09 10:12:05 +03:00
heartbeat = None
loop = True
while loop and tries > -1:
try:
c.execute('BEGIN IMMEDIATE')
2015-09-29 13:11:25 +03:00
c.execute('SELECT * FROM {0} LIMIT 1'.format(self.table_name))
row = c.fetchone()
if row is not None:
2017-11-09 10:12:05 +03:00
id = row[0]
heartbeat = Heartbeat(json.loads(row[1]), self.args, self.configs, _clone=True)
c.execute('DELETE FROM {0} WHERE id=?'.format(self.table_name), [id])
conn.commit()
loop = False
2017-11-09 10:12:05 +03:00
except sqlite3.Error:
2016-09-02 11:50:54 +03:00
log.traceback(logging.DEBUG)
sleep(wait)
tries -= 1
2014-05-27 01:06:36 +04:00
try:
conn.close()
2017-11-09 10:12:05 +03:00
except sqlite3.Error:
2016-09-02 11:50:54 +03:00
log.traceback(logging.DEBUG)
2014-12-22 10:01:09 +03:00
return heartbeat
2017-11-09 10:12:05 +03:00
def push_many(self, heartbeats):
for heartbeat in heartbeats:
self.push(heartbeat)
def pop_many(self, limit=None):
if limit is None:
2018-09-21 08:29:34 +03:00
limit = DEFAULT_SYNC_OFFLINE_ACTIVITY
2017-11-09 10:12:05 +03:00
heartbeats = []
count = 0
2018-09-21 08:29:34 +03:00
while count < limit:
2017-11-09 10:12:05 +03:00
heartbeat = self.pop()
if not heartbeat:
break
heartbeats.append(heartbeat)
count += 1
2018-09-21 08:29:34 +03:00
if count % HEARTBEATS_PER_REQUEST == 0:
yield heartbeats
heartbeats = []
2017-11-09 10:12:05 +03:00
2018-09-21 08:29:34 +03:00
if heartbeats:
yield heartbeats
2017-11-09 10:12:05 +03:00
def _get_db_file(self):
home = '~'
if os.environ.get('WAKATIME_HOME'):
home = os.environ.get('WAKATIME_HOME')
return os.path.join(os.path.expanduser(home), '.wakatime.db')