Skip to content

Add sleep/msg-recv/generator intrinsics, conversion builtins, and multiprocess tests#99

Merged
transfix merged 7 commits into
masterfrom
feat/sleep-intrinsic
May 27, 2026
Merged

Add sleep/msg-recv/generator intrinsics, conversion builtins, and multiprocess tests#99
transfix merged 7 commits into
masterfrom
feat/sleep-intrinsic

Conversation

@transfix
Copy link
Copy Markdown
Owner

@transfix transfix commented May 26, 2026

Summary

Major expansion of the state_exec DSL with new intrinsics, builtins, generator
support, scheduler enhancements, cross-process IPC testing, and comprehensive
developer guide updates.

New Intrinsics

  • sleep — suspend process for N seconds; scheduler auto-wakes on expiry
  • msg-recv — blocking receive: pops from inbox/pending queue, or suspends until a message arrives
  • msg-pending — non-blocking count of queued messages for a given path
  • break — exit loops early from within while/for bodies

New Builtins

Type conversion & predicates

int, float, is-int, is-float, is-string

Standard Library Modules (new)

Module: string (12 functions)

string.length, string.substring, string.contains, string.upper, string.lower, string.split, string.join, string.trim, string.starts-with, string.ends-with, string.replace, string.char-at

Module: math (16 functions)

math.sqrt, math.abs, math.floor, math.ceil, math.round, math.pow, math.log, math.sin, math.cos, math.min, math.max, math.clamp, math.pi, math.e, math.random

Module: collections (12 functions)

collections.map, collections.filter, collections.reduce, collections.zip, collections.flatten, collections.sort, collections.reverse, collections.range, collections.unique, collections.dict-keys, collections.dict-values, collections.dict-merge

Generator Pattern

  • generator.h — lazy sequence generator with yield support
  • Stackless evaluator generator integration
  • for loop and collect consumption

Scheduler Enhancements

  • Bounded message queue with configurable max_pending_messages
  • Settings via state tree: per-scheduler (state_exec.schedulers.<id>.max_pending_messages) and global defaults (state_exec.defaults.max_pending_messages)
  • load_settings() with resolution order: per-scheduler -> global default -> hardcoded fallback
  • Publishes effective config (policy, queue cap) back to state tree
  • Process priority field and priority scheduling policy (round_robin, priority, priority_rr)
  • execute_options struct for named process parameters

Cross-Process IPC Tests

  • 5 IPC tests + 3 gRPC tests for multi-process message passing
  • Producer-consumer integration tests (12 tests)
  • Thread-safety tests for OOB message delivery

Bug Fixes (CI)

  • IPC test hangs: Fixed spin loop exit condition in step()/run(), fixed deliver_to_receivers double-delivery, fixed pipeline test scoping (let -> set), added kill(child, SIGKILL) before blocking waitpid
  • gRPC OOB test: Added missing shard_a.set_transport(&tr_a) so OOB messages reach peer over gRPC transport
  • macOS build: Added missing <thread> and <chrono> includes for std::this_thread::sleep_for
  • IPC replication timing: Seeded signal paths (producers.ready, items.ready, data.ready) so the state_sync_adapter has observers before the first write; replaced wait_for_received(N) with value-polling loops for robustness

Documentation

  • Updated STATE_EXEC_DEVELOPER_GUIDE.md with:
    • Type conversion builtins (int, float, is-int, is-float, is-string)
    • Message receiving (msg-recv, msg-pending) with suspend semantics
    • Sleep intrinsic with duration and auto-wake
    • Message-driven process example pattern
    • Scheduler settings via state tree
    • Updated architecture reference

Test Results

62 builtin + 137 intrinsic + 107 scheduler + 82 integration = 388 tests passing

All 14 CI jobs green (5 Linux, 4 macOS, 4 Windows, 1 clang-format).

transfix added 7 commits May 26, 2026 17:49
…tiprocess tests

New intrinsics:
- sleep: suspend process for N milliseconds
- msg-recv: receive OOB message from another process (blocking)
- msg-pending: check if OOB messages are waiting (non-blocking)
- break: exit loops early from within while/for bodies

New builtins:
- int, float: type conversion functions
- is-int, is-float, is-string: type predicate functions
- map, filter, reduce, range, append, reverse, nth, sort:
  list processing builtins
- apply: call a function with a list of arguments
- str-length, str-substr, str-find, str-upper, str-lower,
  str-split, str-join, str-trim, str-starts-with, str-ends-with,
  str-replace, str-to-list, str-from-list: string operations
- hash-map, hash-get, hash-set, hash-keys, hash-values,
  hash-has, hash-remove, hash-merge, hash-count: hash map operations

Generator pattern:
- generator.h: lazy sequence generator with yield support
- Stackless evaluator generator integration

Scheduler enhancements:
- Bounded message queue with configurable capacity
- Queue accessor intrinsics (msg-queue-size, msg-queue-capacity)
- Scheduler settings via state tree (scheduling.policy,
  scheduling.time-slice-ms, scheduling.max-steps-per-slice)
- Process priority field and priority scheduling policy
- execute_options struct for named process parameters

Cross-process IPC tests:
- 5 IPC tests + 3 gRPC tests for multi-process communication
- Producer-consumer integration tests (12 tests)
- Thread-safety tests for OOB message delivery

62 builtin + 137 intrinsic + 107 scheduler + 82 integration tests
pass (388 total in this changeset).
Add comprehensive documentation for features added in this branch:

- Type conversion builtins: int, float, is-int, is-float, is-string
  with examples and error behavior
- Receiving messages: msg-recv (blocking receive with suspend
  semantics), msg-pending (non-blocking queue depth check)
- Sleep intrinsic: sleep with duration in seconds, auto-wake
- Message-driven process pattern: complete example of a receiver
  loop that accumulates results
- Scheduler settings via state tree: load_settings() with per-scheduler
  and global-default resolution, published effective values
- Updated architecture reference to list new intrinsics
- Fix spin loop in multiprocess tests: break when step() returns 0
  (no ready process to schedule, only waiting processes remain)
- Fix exit condition: use total_processes == terminated + killed
  instead of checking ready/running/paused (missed waiting status)
- Fix deliver_to_receivers double-delivery: remove inbox.push()
  that duplicated message already delivered via stack patch
- Fix Pipeline test scoping: replace let with set to keep loop
  variable in same scope as result accumulator
- Add kill(child, SIGKILL) before blocking waitpid in all IPC tests
Without set_transport, msg-send delivers locally but never
reaches the peer over gRPC, causing OobMessageDelivery to
time out on CI.
The sleep test uses std::this_thread::sleep_for which requires
<thread> and <chrono>. Linux/MSVC include these transitively
but macOS Clang does not.
The state_sync_adapter attaches observers lazily via childChanged,
which propagates after valueChanged has already fired. This means the
very first write to a new path is invisible to the journal. The
multiprocess IPC tests relied on unseed paths like producers.ready
and items.ready being replicated, but those first-writes were silently
dropped.

Fix by:
- Seeding producers.ready, items.ready, and data.ready before the
  scheduler runs so the adapter has observers in place.
- Replacing wait_for_received(N) with polling loops that check for
  the actual expected state values, making the tests robust against
  varying mutation counts.
- Increasing parent-side waitpid timeouts to 30s for CI headroom.
@transfix transfix merged commit f3c881a into master May 27, 2026
14 checks passed
@transfix transfix deleted the feat/sleep-intrinsic branch May 27, 2026 09:57
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant