Closed InteractionEngineer closed 4 months ago
Thanks for reporting this! I've not seen this before. Looking into it.
Firstly, I don't think your records are actually gone.
In addition to storing the records themselves, the app maintains an in-memory data-structure (similar to a binary heap) that allows it to quickly query the summaries that are shown on the right. The _update_bins()
method updates this data structure. This happens recursively. Somehow this recursion resulted in an infinite loop. I don't see how this could have happened.
Could you try to refresh the page? The app should re-build this data structure from the records. It could be that the error persists, but then I have some more info on the cause.
For good measure, also try logging out and in again. That should clear the app's local cache.
Hi there! Thanks for your quick reply. I was also positive about not have lost any data - great to hear this confirmed. Immediately after the error occurred I tried some of the common ways to solve it. I already:
None of these measures helped unfortunately.
Thanks for the feedback! Ok, in that case there is probably something about the record times that causes the recursion.
It would help a lot if I could reproduce the error, so I can explore what's going on. I can than also attempt to fix it, and confirm whether the fix works or not.
If you're up for it, could you please try:
If you don't feel comfortable sending the full data, you could try the following:
Tank you so much for your support - this sounds like a promising procedure. But there is one problem: The error blocks the whole UI, I can't access the menu to provide you an export.
What I forgot to mention: I run this as a Docker container on my home server. If you advise me, I can log into that container and export the wanted file directly.
Can you run a Python script on your work machine? I could create a small script to extract the data via the web api.
Of course, no problem!
import datetime
import requests
# Replace with the url of your instance
base_url = "https://timetagger.app/api/v2/"
# Fill in the api token (from the account page)
api_token = ""
# Get an appropriate range
date1 = datetime.date(2024, 1, 1)
date2 = datetime.date(2024, 12, 31)
timestamp1 = int(time.mktime(date1.timetuple()))
timestamp2 = int(time.mktime(date2.timetuple()))
r = requests.get(base_url + f"records?timerange={timestamp1}-{timestamp2}", headers={"authtoken": api_token})
r.raise_for_status()
records = r.json()["records"]
print("start, stop")
for record in records:
print(f"{record['t1']},{record['t2']}")
Awesome! I quickly ran your script and got the following output:
start, stop 1612982100,1612985640 1620557100,1620557760 1622755080,1622761320 1622797200,1622799180 1624996620,1624998060 1625062920,1625063820
I choose 2020 to 2022 as range because the error occurred entering data from 2021.
Is that all the data (that's just 6 records)?
Indeed, I was just starting to import old data. New data would be from this year. I would prefer not to publish those. Are they important as well? The error surely results out of those 6 entries.
I tried importing these 6, and it did not show the error, unfortunately. You could email me a bigger dataset, so that at least its not public. Or try to find a working subset with the steps:
I tried recreating what you did but didn't succeed. I've emailed you a copy of the output for my complete dataset.
Here's a script to see if there's records with odd dates.
import time
import datetime
import requests
# Replace with the url of your instance
base_url = "https://timetagger.app/api/v2/"
# Fill in the api token (from the account page)
api_token = ""
timestamp1 = 0
timestamp2 = 2218768380000
response = requests.get(base_url + f"records?timerange={timestamp1}-{timestamp2}", headers={"authtoken": api_token})
response.raise_for_status()
records = response.json()["records"]
records = sorted(records, key=lambda r: r["t1"])
def show_record(prefix, r):
dt1 = datetime.datetime.fromtimestamp(r['t1'])
dt2 = datetime.datetime.fromtimestamp(r['t2'])
print(f"{prefix}: {r['key']}, from {dt1} to {dt2}")
print(f"{len(records)} records")
show_record("earliest", records[0])
show_record("latest", records[-1])
early_records = [r for r in records if datetime.datetime.fromtimestamp(r['t1']) < datetime.datetime(2000, 1, 1)]
for r in early_records:
show_record("early", r)
future_records = [r for r in records if datetime.datetime.fromtimestamp(r['t2']) > datetime.datetime(2025, 1, 1)]
for r in future_records:
show_record("future", r)
If there are records in a distant past or far future, these are likely the result of accidentally entering a wrong date in the the record dialog. An these may be causing the issue.
They can be fixed with something like this (I can help out write a more specific script):
def update_record(r):
response = requests.put(base_url + "records", headers={"authtoken": api_token}, json=[r])
response.raise_for_status()
print(f"updated {r['key']}")
# .. update any records
# .. then send each record to server using update_record()
Hi Almar! My output looks like this:
21 records earliest: MAgwqbfM, from 2021-02-10 19:35:00 to 2021-02-10 20:34:00 latest: DBRxTXKV, from 2024-07-15 22:14:28 to 2024-07-15 22:35:00
Seemingly no entries in the too distant past or future.
Oh interesting ...
Try replacing the request with this
response = requests.get(base_url + f"updates?since=0", headers={"authtoken": api_token})
response.raise_for_status()
records = response.json()["records"]
records = sorted(records, key=lambda r: r["t1"])
There we go!
22 records earliest: xNOMAreB, from 1921-02-27 00:19:00 to 1921-02-27 00:43:00 latest: DBRxTXKV, from 2024-07-15 22:14:28 to 2024-07-15 22:35:00 early: xNOMAreB, from 1921-02-27 00:19:00 to 1921-02-27 00:43:00
This should do the trick :) It moves the record back to now, so you can open the UI again, and then edit it properly :)
r = early_records[0]
r['t1'] = time.time() # now
r['t2'] = r['t1'] + 1440 # keep duration
update_record(r)
It work's again! Thank you so much! 🎉
Thanks for your patience to work this out together!
I'm glad we were able to figure it out. I already made a few changes to prevent this from happening to other users. Will make a release shortly.
I'll also add some "diagnostic" commands to the CLI tool, based on the code samples we developed here.
While manually adding entries from the past I pressed enter to confirm my "recording". I used the numpad enter key if that matters. One tag included an "ü" (german "ue") - which was not a problem before, when I confirmed my recordings with a click of the corresponding button. Immediately after pressing enter I saw in the background of the recording dialog that all previous entries were removed. Accessing the app with my credentials now leads to theses error messages: