View Issue Details

IDProjectCategoryView StatusLast Update
0007251Talerwallet (TS core)public2022-05-31 16:25
Reportersebasjm Assigned Tosebasjm  
PrioritynormalSeverityfeatureReproducibilityN/A
Status assignedResolutionopen 
Product Versiongit (master) 
Target Versiongit (master) 
Summary0007251: split operation from other database records (purchase, exchange... )
DescriptionCopy from the previous discussion. We should use this ticket for further discussion.

------

Here is my first iteration of the idea:

struct
---------------

interface Operation {
  recordId: string;
  type: PendingTaskInfo.type
  active: boolean;
  LastError
  RetryInfo
}

the operation primary key is composite by type + recordId (exchange id for exchange-update, orderId for proposals), rationale:
 - there should not be two tasks from the same entity
 - the algorithm should be able to find a pending operation for a known record

 * givesLifeness is defined by task type, no need to keep it in the database.
 * timestampDue is calculated by nextRetry in retryInfo

active: does this operation need to run again? for exchange-update it will always be true and for deposits is true when it doesn't have timestampFinished.
The change here is that now the operation algorithm is not responsible for defining when an operation is active (like gatherProposalPending), the domain logic should define this (exchange or deposit) in its own handler. (see handlerResult below)

RetryInfo and LastError stay the same, but they are no more in the EntityRecords (I have counted 9 records approx with this info)


algorithm
--------------

getPendingOperations(): returns operations with active = true

processOnePendingOperation(taskType, recordId)
 - get the row from the database/cache if exists or create it if don't
 - update retryInfo, increment counter
 - get the entity record (skip if it doesn't)
 - call operation handler with the entityRecord
 - check if error, save lastError (also notify async operation error with task type and recordId )
 - algo, update active flag based on the handler result
 - return last state (also notify async operation update with task type and recordId)

This function will be called periodically (by the retryPolicy) and can also be called from user interaction. If the latter should also take the latest state from the database (or create it) and update it (I found that retryTransaction in transaction.ts do this)

Note that the operation handler should know nothing about retry, forceNow, lastError and the operation itself. It just works and updates the EntityRecord.
The operation logic also knows nothing about the entityRecord, it just needs to handle the case that the operation is still active but the record is not found. In that case, I think we can consider ignoring the situation.

Handler should return
interface HandlerResult<T> {
  pending: boolean;
  state: T
}
if pending is true then the operation is still active and will be run again in the next loop. State can be used for sync calls to the handler.

alternatives:
 - operation with a payload: discarded since the record id should have all the information for the handler to be executed
 - compose the type + recordId into one string and make it the id
 - instead of (task type, id) as PK use (entityRecord, operation name, record Id)
 - we may call event instead of operation and transition instead of the handler and every entity record should have a state name: i think that the main difference here is that an operation assumes the state of the entity (operation = event + transition) which is ok for now but I'm worried (maybe too much) when the javascript is upgraded and used with old databases.
TagsNo tags attached.

Activities

There are no notes attached to this issue.

Issue History

Date Modified Username Field Change
2022-05-31 16:24 sebasjm New Issue
2022-05-31 16:24 sebasjm Status new => assigned
2022-05-31 16:24 sebasjm Assigned To => sebasjm