Skip to content

Commit 34769d8

Browse files
Release 1.1.0 (#83)
* Update dependencies * Update daprd * feat: add shutdown (#80) * feat: add shutdown * Adds params and throw attributes * Add param description * Add a helper to shutdown at the end of the request * Ensure unit tests using the mock client will fail if they try to call the sidecar after shutting it down. * Use POST to shutdown Co-authored-by: Rob Landers <[email protected]> * Add actor reference (#71) * Add actor reference * Add 'get from interface' * Use interface instead * fix bad var name * Add actor reference to tests * Implement an actor reference and address * ok, I think I like the way it works now * Add deprecation to actor reference * Revert format change * Revert comment * Add more tests * not going to deprecate actor proxy After thinking about it and trying to understand usages, I don't think this should be deprecated at this time. Co-authored-by: Hugome <[email protected]>
1 parent f716424 commit 34769d8

File tree

11 files changed

+361
-75
lines changed

11 files changed

+361
-75
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@
4242
"docker-compose up -d"
4343
],
4444
"dapr-init": [
45-
"dapr init --runtime-version 1.0.0"
45+
"dapr init --runtime-version 1.1.0"
4646
],
4747
"clean": [
4848
"docker-compose stop",

composer.lock

Lines changed: 72 additions & 62 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

docker-compose.yml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
version: "3"
33
services:
44
placement:
5-
image: daprio/dapr:1.0.1
5+
image: daprio/dapr:1.1.0
66
command: [ "./placement","-port","50006" ]
77
dev:
88
build:
@@ -20,7 +20,7 @@ services:
2020
- dev
2121
network_mode: service:dev
2222
dev-daprd:
23-
image: daprio/daprd:1.0.1
23+
image: daprio/daprd:1.1.0
2424
command: [ "./daprd","-app-id","dev","-app-port","80","-placement-host-address","placement:50006","-components-path","/components" ]
2525
volumes:
2626
- ./components:/components

src/index.php

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,8 @@
66
define('STORE', 'statestore');
77

88
use Dapr\Actors\ActorProxy;
9+
use Dapr\Actors\ActorReference;
10+
use Dapr\Actors\Generators\ProxyFactory;
911
use Dapr\Actors\IActor;
1012
use Dapr\Actors\Reminder;
1113
use Dapr\Actors\Timer;
@@ -58,13 +60,14 @@ public function increment(int $amount = 1): void
5860

5961
$app->get(
6062
'/test/actors',
61-
function (ActorProxy $actorProxy, DaprClient $client, LoggerInterface $logger) {
62-
$id = uniqid(prefix: 'actor_');
63+
function (ProxyFactory $proxyFactory, DaprClient $client, LoggerInterface $logger) {
64+
$id = uniqid(prefix: 'actor_');
65+
$reference = new ActorReference($id, 'SimpleActor');
6366

6467
/**
6568
* @var ISimpleActor|IActor $actor
6669
*/
67-
$actor = $actorProxy->get(ISimpleActor::class, $id);
70+
$actor = $reference->bind(ISimpleActor::class, $proxyFactory);
6871
$body = [];
6972

7073
$logger->critical('Created actor proxy');
@@ -73,6 +76,10 @@ function (ActorProxy $actorProxy, DaprClient $client, LoggerInterface $logger) {
7376
$body = assert_equals($body, 1, $actor->get_count(), 'Actor should have data');
7477
$logger->critical('Incremented actor');
7578

79+
// get the actor proxy again
80+
$reference = ActorReference::get($actor);
81+
$actor = $reference->bind(ISimpleActor::class, $proxyFactory);
82+
7683
$reminder = new Reminder(
7784
name: 'increment',
7885
due_time: new DateInterval('PT1S'),

src/lib/Actors/ActorProxy.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
use Dapr\Actors\Generators\ProxyFactory;
77
use DI\DependencyException;
88
use DI\NotFoundException;
9+
use JetBrains\PhpStorm\Deprecated;
910
use LogicException;
1011
use Psr\Log\LoggerInterface;
1112
use ReflectionClass;
@@ -29,15 +30,15 @@ public function __construct(protected ProxyFactory $proxyFactory, protected Logg
2930
* Returns an actor proxy
3031
*
3132
* @param string $interface
32-
* @param mixed $id The id to proxy for
33+
* @param string $id
3334
* @param string|null $override_type Allow overriding the Dapr type for a given interface
3435
*
3536
* @return object
36-
* @throws ReflectionException
3737
* @throws DependencyException
3838
* @throws NotFoundException
39+
* @throws ReflectionException
3940
*/
40-
public function get(string $interface, mixed $id, string|null $override_type = null): object
41+
public function get(string $interface, string $id, string|null $override_type = null): object
4142
{
4243
$this->logger?->debug('Getting actor proxy for {i}||{id}', ['i' => $interface, 'id' => $id]);
4344

src/lib/Actors/ActorReference.php

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
<?php
2+
3+
namespace Dapr\Actors;
4+
5+
use Dapr\Actors\Attributes\DaprType;
6+
use Dapr\Actors\Generators\ProxyFactory;
7+
use Dapr\Deserialization\Deserializers\IDeserialize;
8+
use Dapr\Deserialization\IDeserializer;
9+
use Dapr\Serialization\ISerializer;
10+
use Dapr\Serialization\Serializers\ISerialize;
11+
use LogicException;
12+
use ReflectionClass;
13+
14+
/**
15+
* Class ActorReference
16+
* @package Dapr\Actors
17+
*/
18+
final class ActorReference implements IActorReference, ISerialize, IDeserialize
19+
{
20+
public function __construct(private string $id, private string $actor_type)
21+
{
22+
}
23+
24+
/**
25+
* @inheritDoc
26+
*/
27+
public static function get(mixed $actor): IActorReference
28+
{
29+
$id = $actor?->get_id();
30+
31+
if ($id === null) {
32+
throw new LogicException('actor(proxy) must implement get_id()');
33+
}
34+
35+
$detected_dapr_type = self::get_dapr_type($actor);
36+
37+
$dapr_type = $actor->DAPR_TYPE ?? $detected_dapr_type?->type;
38+
39+
if ($dapr_type === null) {
40+
throw new LogicException('Missing DaprType attribute on '.$actor::class);
41+
}
42+
43+
return new self(id: $id, actor_type: $dapr_type);
44+
}
45+
46+
private static function get_dapr_type(object|string $type): DaprType|null
47+
{
48+
$reflector = new ReflectionClass($type);
49+
/**
50+
* @var DaprType|null $type_attribute
51+
*/
52+
$type_attribute = ($reflector->getAttributes(DaprType::class)[0] ?? null)?->newInstance();
53+
54+
return $type_attribute;
55+
}
56+
57+
public static function deserialize(mixed $value, IDeserializer $deserializer): mixed
58+
{
59+
return new ActorReference(id: $value['ActorId'], actor_type: $value['ActorType']);
60+
}
61+
62+
/**
63+
* @inheritDoc
64+
*/
65+
public function bind(string $interface, ProxyFactory $proxy_factory): mixed
66+
{
67+
return $proxy_factory->get_generator($interface, $this->actor_type)->get_proxy(
68+
$this->id
69+
);
70+
}
71+
72+
/**
73+
* @inheritDoc
74+
*/
75+
public function get_actor_id(): string
76+
{
77+
return $this->id;
78+
}
79+
80+
/**
81+
* @inheritDoc
82+
*/
83+
public function get_actor_type(): string
84+
{
85+
return $this->actor_type;
86+
}
87+
88+
/**
89+
* @param ActorReference $value
90+
* @param ISerializer $serializer
91+
*
92+
* @return array
93+
*/
94+
public function serialize(mixed $value, ISerializer $serializer): array
95+
{
96+
return ['ActorId' => $value->id, 'ActorType' => $value->actor_type];
97+
}
98+
}

src/lib/Actors/ActorRuntime.php

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,6 @@
22

33
namespace Dapr\Actors;
44

5-
use Dapr\Actors\Internal\Caches\CacheInterface;
65
use Dapr\Actors\Internal\Caches\FileCache;
76
use Dapr\Actors\Internal\Caches\NoCache;
87
use Dapr\Deserialization\IDeserializer;
@@ -14,7 +13,6 @@
1413
use DI\FactoryInterface;
1514
use DI\NotFoundException;
1615
use Exception;
17-
use JetBrains\PhpStorm\ArrayShape;
1816
use Psr\Log\LoggerInterface;
1917
use ReflectionClass;
2018
use ReflectionException;
@@ -69,7 +67,7 @@ public function do_method(IActor $actor, string $method, mixed $arg): mixed
6967

7068
public function deactivate_actor(IActor $actor, string $dapr_type): void
7169
{
72-
$id = $actor->get_id();
70+
$id = $actor->get_id();
7371
$activation_tracker = hash('sha256', $dapr_type.$id);
7472
$activation_tracker = rtrim(
7573
sys_get_temp_dir(),
@@ -247,7 +245,8 @@ protected function begin_transaction(
247245
*/
248246
protected function get_actor(ReflectionClass $reflection, string $dapr_type, string $id, array $states): IActor
249247
{
250-
$states['id'] = $id;
248+
$states['id'] = $id;
249+
$this->container->set(ActorReference::class, new ActorReference($id, $dapr_type));
251250
$actor = $this->factory->make($reflection->getName(), $states);
252251
$activation_tracker = hash('sha256', $dapr_type.$id);
253252
$activation_tracker = rtrim(

src/lib/Actors/IActorReference.php

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
<?php
2+
3+
namespace Dapr\Actors;
4+
5+
use Dapr\Actors\Generators\ProxyFactory;
6+
7+
/**
8+
* Class IActorReference
9+
* @package Dapr\Actors
10+
*/
11+
interface IActorReference
12+
{
13+
/**
14+
* Get a reference from a given actor that implements IActor
15+
*
16+
* @param IActor $actor The actor or actor interface to extract the reference from
17+
*
18+
* @return IActorReference The actor's reference
19+
*/
20+
public static function get(mixed $actor): IActorReference;
21+
22+
/**
23+
* Get an actor reference bound to a given interface.
24+
*
25+
* @param string $interface The interface of the actor
26+
* @param ProxyFactory $proxy_factory The proxy factory to use
27+
*
28+
* @return IActor The actor's reference
29+
*/
30+
public function bind(string $interface, ProxyFactory $proxy_factory): mixed;
31+
32+
/**
33+
* @return string The actor id
34+
*/
35+
public function get_actor_id(): string;
36+
37+
/**
38+
* @return string The actor type
39+
*/
40+
public function get_actor_type(): string;
41+
}

src/lib/DaprClient.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -201,4 +201,26 @@ public function delete(string $url, ?array $params = []): DaprResponse
201201

202202
return $response;
203203
}
204+
205+
/**
206+
* Shutdown the sidecar.
207+
*
208+
* @return void
209+
* @param array $metadata Metadata to pass to the shutdown endpoint
210+
*
211+
* @throws DaprException
212+
*/
213+
public function shutdown(array $metadata = []): void
214+
{
215+
$this->post("/shutdown", $metadata);
216+
}
217+
218+
/**
219+
* Shutdown the sidecar at the end of the current request.
220+
*
221+
* @param array $metadata Metadata to pass to the shutdown endpoint
222+
*/
223+
public function schedule_shutdown(array $metadata): void {
224+
register_shutdown_function(fn() => $this->shutdown($metadata));
225+
}
204226
}

src/lib/Mocks/TestClient.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,14 @@
1919
class TestClient extends DaprClient
2020
{
2121
public array $responses = [];
22+
private bool $is_shutdown = false;
23+
24+
/**
25+
* Asserts that the sidecar isn't shutdown
26+
*/
27+
private function fail_if_shutdown() {
28+
Assert::assertFalse($this->is_shutdown, 'The sidecar was previously shutdown.');
29+
}
2230

2331
/**
2432
* @param string $url
@@ -29,6 +37,7 @@ class TestClient extends DaprClient
2937
*/
3038
public function get(string $url, ?array $params = null): DaprResponse
3139
{
40+
$this->fail_if_shutdown();
3241
$url = $this->get_api_path($url, $params);
3342
$url = "GET $url";
3443
$this->validate($url, '');
@@ -102,6 +111,7 @@ public function register_get(string $path, int $code, mixed $data): void
102111
*/
103112
public function post(string $url, mixed $data, ?array $params = null): DaprResponse
104113
{
114+
$this->fail_if_shutdown();
105115
$url = $this->get_api_path($url, $params);
106116
$url = "POST $url";
107117
$this->validate($url, json_encode($data, JSON_PRETTY_PRINT));
@@ -143,6 +153,7 @@ public function register_post(
143153
*/
144154
public function delete(string $url, ?array $params = null): DaprResponse
145155
{
156+
$this->fail_if_shutdown();
146157
$url = $this->get_api_path($url, $params);
147158
$url = "DELETE $url";
148159
$this->validate($url, '');
@@ -160,4 +171,15 @@ public function register_delete(string $path, $expected_code): void
160171
$response->code = $expected_code;
161172
$this->responses["DELETE $path"][] = $response;
162173
}
174+
175+
public function shutdown(array $metadata = []): void
176+
{
177+
parent::shutdown($metadata);
178+
$this->is_shutdown = true;
179+
}
180+
181+
public function schedule_shutdown(array $metadata): void
182+
{
183+
// noop because a unit test will never hit it
184+
}
163185
}

0 commit comments

Comments
 (0)