ma3a / SDH-PlayTime

Other
49 stars 5 forks source link

Your are loosing playtime when steam crashed #31

Open ma3a opened 1 year ago

ma3a commented 1 year ago

So it is not possible to solve this fully, but here some ideas that we could do, to minimise amount of time that could be lost:

First one seems to be a good solution, but it significantly increase complexity of the system:

Jaynator495 commented 1 year ago

1 & 4 would probably be ideal for saving as much without performance penalty; I came here to see if this issue was known since I keep losing dozens of hours in TOTK when my deck crashes

SilentException commented 1 year ago

I don't think complexity of saving would go over the roof. Game start event should be logged to a new DB table and then time appended each minute or so to that record (should always be only one record). The record is then persisted to gameplay data table when

(I was already tinking about this few months back but had no time to do anything yet)

ma3a commented 1 year ago

The record is then persisted to gameplay data table when

You mean holding transaction?

Waiting until this events:

  • game stop event is triggered
  • a different game start event is triggered
  • on plugin start

could be potentially risky in normal use cases. For example after crash, user could be so upset, that he just turn off the deck, and when he could start deck again after 1 or 2 days.

a new DB table

Intermediate state could be a bad thing as well - you have to have some logic on startup / event that will transform intermediate state into something concrete.

I was thinking about this: So the current schema of PlayTime database is:

CREATE TABLE play_time(
                        date_time TEXT,
                        duration INT,
                        game_id TEXT,
                        migrated TEXT,
                    )

When we detect that game is running, we are making on FE side session-id. And on tick of sending interval we are sending this session-id. When BE received new interval we are checking is there any interval with same session-id, and if yes, we increment existing duration with interval. If no - just creating new one. So BE in that case stores snapshots of concrete state, without any need to have any intermediate states, or any knowledge of lifecycle FE application.

SilentException commented 1 year ago

The record is then persisted to gameplay data table when

You mean holding transaction?

No, no need to hold transactions, my idea was to have new table with row that would represent playtime for that session.

Waiting until this events:

  • game stop event is triggered
  • a different game start event is triggered
  • on plugin start

could be potentially risky in normal use cases. For example after crash, user could be so upset, that he just turn off the deck, and when he could start deck again after 1 or 2 days.

That wouldn't mean anything, the state would be moved from new table to play_time and nothing would be lost.

a new DB table

Intermediate state could be a bad thing as well - you have to have some logic on startup / event that will transform intermediate state into something concrete.

Yes, i didn't see the problem with that logic. It is simply taking snapshot data from one table and putting it in play_time.

I was thinking about this: So the current schema of PlayTime database is:

CREATE TABLE play_time(
                        date_time TEXT,
                        duration INT,
                        game_id TEXT,
                        migrated TEXT,
                    )

When we detect that game is running, we are making on FE side session-id. And on tick of sending interval we are sending this session-id. When BE received new interval we are checking is there any interval with same session-id, and if yes, we increment existing duration with interval. If no - just creating new one. So BE in that case stores snapshots of concrete state, without any need to have any intermediate states, or any knowledge of lifecycle FE application.

I think the idea here is really similar, bit different execution :) I had snapshots separated from play_time table and transferred to play_time when certain events happen.

This is very doable (y)

ma3a commented 1 year ago

I had snapshots separated from play_time table and transferred to play_time when certain events happen.

It would be very similar to what we already have when processing events from steam. SessionPlayTime is reducer of all game specific events, and it produce event when we need to save something. So if we start handing those events on BE, that the logic will be in two places. As a result there is need to passthrough those events to BE (which will be knowing about game-start, game-end), and handle them as well on FE.

In my suggestion database always in consistent state (from business logic perspective) - there is no unfinished work that we need to do. Whenever you query something - you always get a correct state.

SilentException commented 1 year ago

Yes I completely understand but the approach is not without it's flaws either. Each minute there will be a select over playtimes table to find matching session id. This operation will be more and more expensive over time. Also if we're being pedantic, I do think sessionId is out of place in this table. It is just a temporary thing without any future value. Just to be clear I don't yet have clear oppinion on what is best, just expressing my thoughts: )