PhotoFlow Documentation Help

Album Workflow - State Machine

Overview

The Album Workflow is the core business logic of PhotoFlow, implementing a state machine that manages photo albums through their lifecycle—from initial creation to final delivery.

Album States

The album progresses through the following states:

State

Description

Entry Condition

Init

Album created, waiting for raw photos

Album creation

Raw

Raw photos uploaded and synced

SyncRawTag trigger

Stock

Photos processed, ready for client rating

SyncStockTag trigger + Raw tag Ready

Rate

Client confirmed rating completion

Rate trigger

ConfirmRate

Photographer syncs rated photos

Rate trigger

Retouch

Photos being retouched

ConfirmRate trigger

Feedback

Client reviewing retouched photos

FinishRetouch trigger

NeedRevision

Client requested changes

RequestRevision trigger

ConfirmedFeedback

Client approved all photos

ConfirmFeedback trigger

Finish

Final state with approved photos

Finish trigger

Closed

Album archived/completed

Close trigger

State Machine Diagram

SyncRawTag

Close

SyncRawTag (reentry)

SyncStockTag [RawTagReady]

Close

SyncStockTag (reentry)

Rate [StockTagReady]

Close

Rate

Close

ConfirmRate [StockTagReady]

Close

FinishRetouch [RetouchTagReady]

Finish [RetouchTagReady]

Close

RequestRevision

ConfirmFeedback

Close

FinishRetouch

Finish [RetouchComplete]

Close

Finish [RetouchComplete]

Close

Init

Raw

Closed

Stock

Rate

ConfirmRate

Retouch

Feedback

Finish

NeedRevision

ConfirmedFeedback

Triggers

Trigger

Description

Who Can Execute

SyncRawTag

Upload/sync raw photos from Google Drive

Photographer

SyncStockTag

Process and prepare photos for rating

Photographer

Rate

Client confirms rating is complete

Anonymous

ConfirmRate

Sync rated photos to Google Drive

Photographer

FinishRetouch

Complete retouching, ready for feedback

Photographer

RequestRevision

Client requests changes to photos

Anonymous

ConfirmFeedback

Client approves all photos

Anonymous

Finish

Finalize album with approved photos

Photographer

Close

Archive/close album

Admin

Album Tag Types

Each state corresponds to an Album Tag that holds the photos for that stage:

Tag Type

Description

Created During

Raw

Original raw photos

Init → Raw transition

Stock

Processed stock photos

Raw → Stock transition

Rate

Photos after client rating

Stock → Rate transition

Retouch

Retouched photos

Rate → Retouch transition

Final

Final approved photos

→ Finish transition

Album Tag Status

public enum EnumAlbumTagStatus { WaitingInputUrl = 1, // Waiting for Google Drive URL WaitingToSync = 2, // URL provided, waiting to sync Syncing = 3, // Sync in progress SyncFailed = 4, // Sync failed, needs retry Rate = 5, // Ready for rating Ready = 6, // Tag is ready for next transition InActive = 7 // Tag is inactive/archived }

State Machine Implementation

The state machine is implemented using the Stateless library:

public class AlbumStateMachineDefinition : IStateMachineDefinition<AlbumEntity, AlbumState, AlbumTrigger> { public void Configure(StateMachine<AlbumState, AlbumTrigger> stateMachine, AlbumEntity entity) { // Configure Init state stateMachine.Configure(AlbumState.Init) .Permit(AlbumTrigger.SyncRawTag, AlbumState.Raw) .Permit(AlbumTrigger.Close, AlbumState.Closed); // Configure Raw state with conditional transition stateMachine.Configure(AlbumState.Raw) .PermitIf(AlbumTrigger.SyncStockTag, AlbumState.Stock, () => IsRawTagReadyForStockTransition(entity)) .PermitReentry(AlbumTrigger.SyncRawTag) .Permit(AlbumTrigger.Close, AlbumState.Closed); // ... additional state configurations } }

Transition Validation

Each transition validates the corresponding AlbumTag status:

Transition

Validation

Raw → Stock

Raw tag status == Ready

Stock → Rate

Stock tag status == Ready

ConfirmRate → Retouch

Stock tag status == Ready

Retouch → Feedback

Retouch tag status == Ready/WaitingToSync/WaitingInputUrl/SyncFailed

Retouch → Finish

Retouch tag status == Ready

ConfirmedFeedback → Finish

Retouch tag status == Ready

Workflow Scenarios

Scenario 1: Normal Flow (No Revisions)

Init → Raw → Stock → Rate → ConfirmRate → Retouch → Feedback → ConfirmedFeedback → Finish

Scenario 2: With Revision Cycle

Init → Raw → Stock → Rate → ConfirmRate → Retouch → Feedback → NeedRevision → Feedback → ConfirmedFeedback → Finish

Scenario 3: Direct Finish from Retouch

Init → Raw → Stock → Rate → ConfirmRate → Retouch → Finish

SignalR Notifications

State transitions trigger SignalR notifications:

Event

Trigger

Payload

AlbumStateChanged

Any state transition

albumId, oldState, newState

AlbumTagCreated

New tag created

albumId, albumTagId, type

AlbumTagStatusChanged

Tag status change

albumId, albumTagId, oldStatus, newStatus

PhotoSyncProgress

During sync

albumId, processedCount, totalCount

PhotoSyncCompleted

Sync finished

albumId, totalCount

API Endpoints

Get Available Transitions

GET /api/v1/albums/{albumId}/transitions Authorization: Bearer <token>

Response:

{ "transitions": [ { "event": "SyncStockTag", "fromState": "Raw", "toState": "Stock", "isRetry": false, "disable": false, "disableReason": null } ] }

Trigger State Change

PUT /api/v1/albums/{albumId}/state Authorization: Bearer <token> Content-Type: application/json { "trigger": "SyncStockTag" }

Error Handling and Rollback

The system includes automatic rollback for failed transitions:

public class AlbumRollbackStrategy : IRollbackStrategy { public async Task RollbackAsync(AlbumEntity entity, AlbumState previousState, ...) { // Record failure var failure = FailureRecordEntity.Create( entity.Id, previousState.ToString(), entity.AlbumState.ToString(), errorMessage, FailureSeverity.High ); // Revert state entity.AlbumState = previousState; // Persist changes await _unitOfWork.SaveChangesAsync(cancellationToken); } }
  • Photo Synchronization

  • Client Feedback Portal

  • Authorization Policies

Last modified: 25 February 2026