# Demonstrates: lock, decode/parse CEL functions, repeat, wait-until
# Patterns: mutual exclusion, structured data decoding, post-condition loops, timestamp-based waiting

flowmarkup:
  title: Lock and Decode Patterns
  version: 1
  description: Demonstrates lock, decode/parse CEL functions, repeat, and wait-until directives
  requires:
    SERVICES: [pricer, confirmation]

  input:
    api_response:
      $kind: TEXT
      _notes_: Raw JSON string from an external API
    scheduled_at:
      $kind: STRING
      _notes_: ISO 8601 timestamp for when processing should begin

  output:
    total: INTEGER
    parsed_items: JSON
  examples:
    two_items:
      _notes_: Two items priced and summed under lock
      input:
        api_response: '{"items":[{"sku":"WG-1001","quantity":2},{"sku":"AC-2003","quantity":1}]}'
        scheduled_at: "2025-01-15T09:00:00Z"
      output:
        total: 250
        parsed_items:
        - sku: WG-1001
          quantity: 2
        - sku: AC-2003
          quantity: 1
    single_item:
      _notes_: Single item response
      input:
        api_response: '{"items":[{"sku":"WG-2002","quantity":5}]}'
        scheduled_at: "2025-06-01T08:00:00Z"
      output:
        total: 500
        parsed_items:
        - sku: WG-2002
          quantity: 5

  vars:
    running_total: 0
    attempt_count: 0
    poll_result:

  do:
    # --- Pattern 1: wait-until — pause until a scheduled time ---
  - waitUntil:
      timestamp: =scheduled_at
      timeout: 24h
      _label_: Wait for scheduled processing time

    # --- Pattern 2: decode/parse — extract structured data from a raw string ---
    # parse() is an alias for decode() — use whichever reads more naturally
  - set:
      parsed_data: =api_response.parse(JSON)
      _label_: Decode API response as JSON

  - assert: =parsed_data.items != null

    # --- Pattern 3: lock — protect a shared accumulator ---
  - forEach:
      items: =parsed_data.items
      maxItems: 10000
      concurrent: true
      maxConcurrency: 5
      do:
      - call:
          service: =SERVICES.pricer
          operation: get_price
          timeout: 30s
          params:
            sku: =item.sku
            quantity: =item.quantity
          result:
            item_price: =RESULT.price

      - lock:
          name: running_total
          scope: LOCAL
          do:
          - set:
              running_total: =running_total + item_price

    # --- Pattern 4: repeat — post-condition loop (runs at least once) ---
  - repeat:
      _label_: Poll until confirmation received
      timeout: 5m
      until: =poll_result == 'confirmed'
      do:
      - set:
          attempt_count: =attempt_count + 1

      - call:
          service: =SERVICES.confirmation
          operation: check_status
          timeout: 30s
          params:
            total: =running_total
          result:
            poll_result: =RESULT.status

      - wait:
          condition: =poll_result != 'confirmed'
          duration: 5s
  - return:
      total: =running_total
      parsed_items: =parsed_data.items
