Skip to content

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
* develop:
  specify next release
  replace publishing a github page by directly linking to the documentation files
  update notes style
  require innmind/file-watch 4
  update documentation to use the new IO syntax
  flag named constructors internal to allow bc breaks in minor versions
  wrap server sockets in an IO
  wrap client sockets in an IO class
  add Filesystem::temporary()
  fix psalm error
  CS
  update actions versions
  • Loading branch information
Baptouuuu committed Mar 10, 2024
2 parents f3282d5 + 942f857 commit 060b925
Show file tree
Hide file tree
Showing 36 changed files with 361 additions and 247 deletions.
8 changes: 4 additions & 4 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ jobs:
name: 'PHPUnit'
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -26,7 +26,7 @@ jobs:
dependency-versions: ${{ matrix.dependencies }}
- name: PHPUnit
run: php -dmemory_limit=-1 vendor/bin/phpunit --coverage-clover=coverage.clover
- uses: codecov/codecov-action@v1
- uses: codecov/codecov-action@v3
with:
token: ${{ secrets.CODECOV_TOKEN }}
psalm:
Expand All @@ -38,7 +38,7 @@ jobs:
name: 'Psalm'
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand All @@ -58,7 +58,7 @@ jobs:
name: 'CS'
steps:
- name: Checkout
uses: actions/checkout@v2
uses: actions/checkout@v4
- name: Setup PHP
uses: shivammathur/setup-php@v2
with:
Expand Down
26 changes: 0 additions & 26 deletions .github/workflows/documentation.yml

This file was deleted.

65 changes: 0 additions & 65 deletions .journal

This file was deleted.

20 changes: 20 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,25 @@
# Changelog

## 5.0.0 - 2024-03-10

### Added

- `Innmind\OperatingSystem\Filesystem::temporary()`

### Changed

- `Innmind\OperatingSystem\Remote::socket()` returned socket is now wrapped in a `Innmind\IO\Sockets\Client`
- `Innmind\OperatingSystem\Sockets::connectTo()` returned socket is now wrapped in a `Innmind\IO\Sockets\Client`
- `Innmind\OperatingSystem\Sockets::open()` returned socket is now wrapped in a `Innmind\IO\Sockets\Server`
- `Innmind\OperatingSystem\Sockets::takeOver()` returned socket is now wrapped in a `Innmind\IO\Sockets\Server`
- `Innmind\OperatingSystem\Ports::open()` returned socket is now wrapped in a `Innmind\IO\Sockets\Server`
- `Innmind\OperatingSystem\CurrentProcess\Generic::of()` is now declared `internal`
- `Innmind\OperatingSystem\Filesystem\Generic::of()` is now declared `internal`
- `Innmind\OperatingSystem\Ports\Unix::of()` is now declared `internal`
- `Innmind\OperatingSystem\Remote\Generic::of()` is now declared `internal`
- `Innmind\OperatingSystem\Ports\Sockets::of()` is now declared `internal`
- Requires `innmind/file-watch:~4.0`

## 4.2.0 - 2023-12-14

### Added
Expand Down
16 changes: 12 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,19 @@ Abstraction for most of the operating system the PHP code run on.

The goal is to deal with the operating system in a more abstract way (instead of dealing with concrete, low level, details).

**Important**: you must use [`vimeo/psalm`](https://packagist.org/packages/vimeo/psalm) to make sure you use this library correctly.
> [!IMPORTANT]
> you must use [`vimeo/psalm`](https://packagist.org/packages/vimeo/psalm) to make sure you use this library correctly.
## Installation

```sh
composer require innmind/operating-system
```

## Documentation

Documentation is located in the [`documentation/`](documentation) folder.

## Usage

```php
Expand Down Expand Up @@ -70,7 +75,7 @@ $server = $os
Port::of(1337),
)
->match(
static fn($server) => $server,
static fn($server) => $server->unwrap(),
static fn() => throw new \RuntimeException('Cannot open the socket'),
);
```
Expand All @@ -84,7 +89,7 @@ $server = $os
use Innmind\Socket\Address\Unix;

$server = $os->sockets()->open(Unix::of('/tmp/foo.sock'))->match(
static fn($server) => $server,
static fn($server) => $server->unwrap(),
static fn() => throw new \RuntimeException('Cannot open the socket'),
);
```
Expand All @@ -95,7 +100,10 @@ $server = $os->sockets()->open(Unix::of('/tmp/foo.sock'))->match(
# process B
use Innmind\Socket\Address\Unix;

$client = $os->sockets()->connectTo(Unix::of('/tmp/foo.sock'));
$client = $os->sockets()->connectTo(Unix::of('/tmp/foo.sock'))->match(
static fn($client) => $client->unwrap(),
static fn() => throw new \RuntimeException('Cannot connect to the socket'),
);
```

`$client` is an instance of `Innmind\Socket\Client`.
Expand Down
4 changes: 2 additions & 2 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,10 +24,10 @@
"innmind/http-transport": "~7.2",
"innmind/time-warp": "~3.0",
"innmind/signals": "~3.0",
"innmind/file-watch": "~3.1",
"innmind/file-watch": "~4.0",
"innmind/stream": "~4.0",
"formal/access-layer": "^2.0",
"innmind/io": "~2.2"
"innmind/io": "~2.7"
},
"autoload": {
"psr-4": {
Expand Down
3 changes: 2 additions & 1 deletion documentation/advanced/logging.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,8 @@

If you want to trace everything that is done on your operating system you can use the logger decorator that will automatically write to your log file (almost) all operations.

**Note**: data and actions done on a socket are not logged as well as processes output to prevent logging too much data (at least for now).
> [!NOTE]
> data and actions done on a socket are not logged as well as processes output to prevent logging too much data (at least for now).
```php
use Innmind\OperatingSystem\OperatingSystem\Logger;
Expand Down
22 changes: 20 additions & 2 deletions documentation/readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,8 @@ The other advantage to use higher level abstractions is to enable end user to bu

For concrete examples have a look at the use cases available in the sidebar.

**Note**: this library is a small overlay on top of a set of individual libraries that contain the concrete abstractions. So you can start using only a subset of abstractions in your code as a starting point.
> [!NOTE]
> this library is a small overlay on top of a set of individual libraries that contain the concrete abstractions. So you can start using only a subset of abstractions in your code as a starting point.
## Installation

Expand All @@ -26,4 +27,21 @@ $os = Factory::build();

There's nothing more to add to start using this abstraction. Head toward the use cases to understand all the things you can do with it.

**Note**: This library doesn't work on windows environments.
> [!WARNING]
> This library doesn't work on windows environments.
## Use cases

- [Manipulating time](use_cases/time.md)
- [Filesystem](use_cases/filesystem.md)
- [HTTP Client](use_cases/http.md)
- [Processes](use_cases/processes.md)
- [Inter Process Communication](use_cases/ipc.md)
- [Socket communication](use_cases/socket.md)
- [Handling process signals](use_cases/signals.md)
- [SQL connection](use_cases/sql.md)

## Advanced usage

- [Logging all operations](advanced/logging.md)
- [Extensions](advanced/extensions.md)
16 changes: 8 additions & 8 deletions documentation/use_cases/filesystem.md
Original file line number Diff line number Diff line change
Expand Up @@ -112,24 +112,24 @@ It is a great way to forget about where the tmp folder is located and simply foc
A pattern we don't see much in PHP is an infinite loop to react to an event to perform another task. Here we can build such pattern by watching for changes in a file or a directory.

```php
use Innmind\FileWatch\Stop;
use Innmind\Immutable\Either;
use Innmind\FileWatch\Continuation;

$runTests = $os->filesystem()->watch(Path::of('/path/to/project/src/'));

$count = $runTests(0, function(int $count) use ($os): Either {
$count = $runTests(0, function(int $count, Continuation $continuation) use ($os): Continuation {
if ($count === 42) {
return Either::left(Stop::of($count));
return $continuation->stop($count);
}

$os->control()->processes()->execute($phpunitCommand);

return Either::right(++$count);
return $continuation->continue(++$count);
});
```

Here it will run phpunit tests every time the `src/` folder changes. Concrete examples of this pattern can be found in [`innmind/lab-station`](https://github.com/Innmind/LabStation/blob/develop/src/Agent/WatchSources.php#L38) to run a suite of tools when sources change or in [`halsey/journal`](https://github.com/halsey-php/journal/blob/develop/src/Command/Preview.php#L58) to rebuild the website when the markdown files change.
Here it will run phpunit tests every time the `src/` folder changes. Concrete examples of this pattern can be found in [`innmind/lab-station`](https://github.com/Innmind/LabStation/blob/develop/src/Agent/WatchSources.php#L38) to run a suite of tools when sources change.

This operation is a bit like an `array_reduce` as you can keep a state record between each calls of the callable via the first argument (here `0`, but it can be anything) and the argument of your callable will be the previous value returned by `Either::right()`.
This operation is a bit like an `array_reduce` as you can keep a state record between each calls of the callable via the first argument (here `0`, but it can be anything) and the argument of your callable will be the previous value returned by `$continuation->continue()`.

**Important**: since there is not builtin way to watch for changes in a directory it checks the directory every second, so use it with care. Watching an individual file is a bit safer as it uses the `tail` command so there is no `sleep()` used.
> [!WARNING]
> since there is no builtin way to watch for changes in a directory it checks the directory every second, so use it with care. Watching an individual file is a bit safer as it uses the `tail` command so there is no `sleep()` used.
6 changes: 4 additions & 2 deletions documentation/use_cases/http.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,8 @@ $response instanceof Response; // true

All elements of a request/response call is built using objects to enforce correctness of the formatted messages.

**Note**: since request and responses messages can be viewed either from a client or a server the model is abstracted in the standalone [`innmind/http` library](https://github.com/innmind/http).
> [!NOTE]
> since request and responses messages can be viewed either from a client or a server the model is abstracted in the standalone [`innmind/http` library](https://github.com/innmind/http).
## Resiliency in a distributed system

Expand Down Expand Up @@ -62,4 +63,5 @@ $response = $http($request);
$response = $http($request);
```

**Note**: the circuit breaker works on host per host basis meaning if `server1.com` fails then calls to `server2.com` will still be sent.
> [!NOTE]
> the circuit breaker works on host per host basis meaning if `server1.com` fails then calls to `server2.com` will still be sent.
54 changes: 28 additions & 26 deletions documentation/use_cases/ipc.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,17 @@ To communicate between processes on a same system there is 2 approaches: sharing

The later is the safest of the two (but not exempt of problems) and you will find here the building blocks to communicate via a socket.

**Note**: the adage `share state through messages and not messages through state` is a pillar of the [actor model](https://en.wikipedia.org/wiki/Actor_model) and [initially of object oriented programming](https://www.youtube.com/watch?v=7erJ1DV_Tlo).
> [!TIP]
> the adage `share state through messages and not messages through state` is a pillar of the [actor model](https://en.wikipedia.org/wiki/Actor_model) and [initially of object oriented programming](https://www.youtube.com/watch?v=7erJ1DV_Tlo).
```php
# process acting as a server
use Innmind\Socket\Address\Unix as Address;
use Innmind\TimeContinuum\Earth\ElapsedPeriod;
use Innmind\Immutable\Str;
use Innmind\Immutable\{
Sequence,
Str,
};

$server = $os->sockets()->open(Address::of('/tmp/foo'))->match(
static fn($server) => $server,
Expand All @@ -19,45 +23,43 @@ $server = $os->sockets()->open(Address::of('/tmp/foo'))->match(
$watch = $os->sockets()->watch(new ElapsedPeriod(1000))->forRead($server);

while (true) {
$watch()
->flatMap(static fn($ready) => $ready->toRead()->find(static fn($socket) => $socket === $stream))
->flatMap(static fn($server) => $server->accept())
$_ = $server
->timeoutAfter(ElapsedPeriod::of(1_000))
->accept()
->match(
static fn($client) => $client
->write(Str::of('Hello 👋'))
->flatMap(static fn($client) => $client->close())
->send(Sequence::of(Str::of('Hello')))
->flatMap(static fn() => $client->close())
->match(
static fn() => null, // everyhting is ok
static fn() => throw new \RuntimeException('Unable to send data or close the connection'),
),
static fn() => null, // no new connection available
);
),
}
```

```php
# process acting as client
use Innmind\Socket\Address\Unix as Address;
use Innmind\TimeContinuum\Earth\ElapsedPeriod;

$client = $os->sockets()->connectTo(Address::of('/tmp/foo'));
$watch = $os->sockets()->watch(new ElapsedPeriod(1000))->forRead($client);
use Innmind\IO\Readable\Frame;

do {
$ready = $watch()
->flatMap(static fn($ready) => $ready->toRead()->find(static fn($ready) => $ready === $client))
->match(
static fn() => true,
static fn() => false,
);
} while (!$ready);

echo $client->read()->match(
static fn($data) => $data->toString(),
static fn() => 'unable to read the stream',
$client = $os->sockets()->connectTo(Address::of('/tmp/foo'))->match(
static fn($client) => $client,
static fn() => throw new \RuntimeException('Unable to connect to the server'),
);

echo $client
->watch()
->frames(Frame\Chunk::of(5))
->one()
->match(
static fn($data) => $data->toString(),
static fn() => 'unable to read the stream',
);
```

In the case the server is started first then the client would print `Hello 👋`.
In the case the server is started first then the client would print `Hello`.

**Important**: this is a very rough implementation of communication between processes. **DO NOT** use this simple implementation in your code, instead use a higher level API such as [`innmind/ipc`](https://github.com/innmind/ipc).
> [!WARNING]
> this is a very rough implementation of communication between processes. **DO NOT** use this simple implementation in your code, instead use a higher level API such as [`innmind/ipc`](https://github.com/innmind/ipc).
Loading

0 comments on commit 060b925

Please sign in to comment.