Skip to content

0.19.0

Latest

Choose a tag to compare

@ponylang-main ponylang-main released this 21 Aug 16:17
· 3 commits to main since this release

Remove is_open() from TCPConnection

is_open() has been removed from TCPConnection. Code that queried connection state before acting should instead call the operation directly and handle the result.

Before:

if _tcp_connection.is_open() then
  _tcp_connection.send(data)
end

After:

match _tcp_connection.send(data)
| SendAccepted => // sent
| SendErrorNotConnected => // not connected or closed
| SendErrorNotWriteable => // backpressure
end

Make TCPConnection and TCPListener generic over TCPBackend

TCPConnection, TCPListener, and the related actor and lifecycle receiver traits now take a type parameter TCP: TCPBackend ref = RuntimeBackend. The default means existing code compiles unchanged — bare TCPConnection and TCPListener resolve to the RuntimeBackend instantiation without a type argument.

TCPBackend is a public trait. A test fake that implements it can drive the connection state machine without real sockets. Pony fully reifies generics, so each instantiation compiles to direct calls with no runtime dispatch overhead.

Rename PonyTCP to RuntimeBackend

PonyTCP has been renamed to RuntimeBackend and changed from a primitive to a class. Code that references PonyTCP by name should use RuntimeBackend instead.

Before:

PonyTCP.writev_max()

After:

RuntimeBackend.writev_max()

Fix resource leak when disposing a server connection during initialization

Disposing a server-side TCPConnection before it finished initializing leaked an ASIO event. The leaked event was noisy, so the runtime would not exit. This could happen when a listener disposed an accepted connection immediately — the dispose could arrive before the connection's deferred initialization, since the two messages come from different actors.

Several TCPConnection and TCPListener methods now require a ref receiver

TCPConnection.keepalive, TCPConnection.local_address, TCPConnection.remote_address, and TCPListener.local_address are now fun ref instead of fun box. Code that calls any of these through a box reference needs a ref reference instead.

Add notifier-based TCP API subpackage

A new lori/notifier subpackage provides a convenience layer over lori's native class-and-trait API. You write a notifier class with the callbacks you care about and hand it to a concrete actor — no actor boilerplate, no trait wiring.

Three actor/notifier pairs cover client connections, server connections, and listeners:

use "lori"
use "lori/notifier"

class Echo is ServerTCPConnectionNotify
  fun ref on_start_failure(conn: ServerTCPConnection ref,
    reason: StartFailureReason)
  =>
    None

  fun ref on_received(conn: ServerTCPConnection ref, data: Array[U8] iso):
    ReadAction
  =>
    conn.write(consume data)
    KeepReading

class EchoListen is TCPListenNotify
  fun ref on_connected(listen: TCPListener ref):
    ServerTCPConnectionNotify iso^
  =>
    Echo
  fun ref on_not_listening(listen: TCPListener ref) =>
    None

actor Main
  new create(env: Env) =>
    TCPListener(TCPListenAuth(env.root), recover EchoListen end, "", "8989")

write and mute are behaviors rather than synchronous methods, and SSL is configured through a constructor (.ssl) rather than a separate class. Use the notifier API for straightforward applications; use lori's native API when you need synchronous send results, custom actor structure, or multiple connections per actor.

Require explicit start-failure handling for server connections

ServerLifecycleEventReceiver and ServerTCPConnectionNotify no longer provide a default for start-failure handling. Every implementor must now provide an explicit method body.

Native API — before:

actor MyServer is (TCPConnectionActor & ServerLifecycleEventReceiver)
  var _tcp_connection: TCPConnection = TCPConnection.none()

  fun ref _connection(): TCPConnection =>
    _tcp_connection

Native API — after:

actor MyServer is (TCPConnectionActor & ServerLifecycleEventReceiver)
  var _tcp_connection: TCPConnection = TCPConnection.none()

  fun ref _connection(): TCPConnection =>
    _tcp_connection

  fun ref _on_start_failure(reason: StartFailureReason) =>
    None

Notifier API — before:

class MyNotify is ServerTCPConnectionNotify
  fun ref on_received(conn: ServerTCPConnection ref, data: Array[U8] iso):
    ReadAction
  =>
    KeepReading

Notifier API — after:

class MyNotify is ServerTCPConnectionNotify
  fun ref on_start_failure(conn: ServerTCPConnection ref,
    reason: StartFailureReason)
  =>
    None

  fun ref on_received(conn: ServerTCPConnection ref, data: Array[U8] iso):
    ReadAction
  =>
    KeepReading

Require explicit connection-failure handling for client connections

ClientLifecycleEventReceiver no longer provides a default for _on_connection_failure. Every implementor must now provide an explicit method body.

Before:

actor MyClient is (TCPConnectionActor & ClientLifecycleEventReceiver)
  var _tcp_connection: TCPConnection = TCPConnection.none()

  fun ref _connection(): TCPConnection =>
    _tcp_connection

After:

actor MyClient is (TCPConnectionActor & ClientLifecycleEventReceiver)
  var _tcp_connection: TCPConnection = TCPConnection.none()

  fun ref _connection(): TCPConnection =>
    _tcp_connection

  fun ref _on_connection_failure(reason: ConnectionFailureReason) =>
    None

[0.19.0] - 2026-08-21

Fixed

  • Fix resource leak when disposing a server connection during initialization (PR #368)

Added

  • Add notifier-based TCP API subpackage (PR #371)

Changed

  • Remove is_open() from TCPConnection (PR #365)
  • Make TCPConnection and TCPListener generic over TCPBackend (PR #366)
  • Rename PonyTCP to RuntimeBackend (PR #366)
  • Change RuntimeBackend from a primitive to a class (PR #369)
  • Several TCPConnection and TCPListener methods now require a ref receiver (PR #369)
  • Require explicit start-failure handling for server connections (PR #377)
  • Require explicit connection-failure handling for client connections (PR #379)