Skip to content

Commit 5a107de

Browse files
Restore Waterline legacy detail metadata fallbacks
Preserve legacy detail visibility metadata
1 parent 846bf7f commit 5a107de

2 files changed

Lines changed: 140 additions & 0 deletions

File tree

app/Http/Resources/V2StoredWorkflowResource.php

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
namespace Waterline\Http\Resources;
44

5+
use Illuminate\Database\Eloquent\Model;
56
use Illuminate\Http\Resources\Json\JsonResource;
7+
use Illuminate\Support\Facades\DB;
68
use Workflow\V2\Contracts\OperatorObservabilityRepository;
79
use Workflow\V2\Models\WorkflowRun;
810
use Waterline\Support\ActionabilityContract;
@@ -77,13 +79,24 @@ private function withLegacyVisibilityMetadata(array $detail): array
7779

7880
$detail['memo'] = VisibilityMetadataBridge::preserve(
7981
$detail['memo'] ?? null,
82+
$this->resource->memo,
83+
$this->attributeValue($this->resource, 'memo'),
8084
$this->resource->getRawOriginal('memo'),
85+
$this->resource->instance?->memo,
86+
$this->attributeValue($this->resource->instance, 'memo'),
8187
$this->resource->instance?->getRawOriginal('memo'),
88+
$this->databaseAttributeValue($this->resource, 'memo'),
89+
$this->databaseAttributeValue($this->resource->instance, 'memo'),
8290
);
8391
$detail['search_attributes'] = VisibilityMetadataBridge::preserve(
8492
$detail['search_attributes'] ?? null,
93+
$summary?->search_attributes,
94+
$this->attributeValue($summary, 'search_attributes'),
8595
$summary?->getRawOriginal('search_attributes'),
96+
$this->resource->search_attributes,
97+
$this->attributeValue($this->resource, 'search_attributes'),
8698
$this->resource->getRawOriginal('search_attributes'),
99+
$this->databaseAttributeValue($this->resource, 'search_attributes'),
87100
);
88101

89102
return $detail;
@@ -133,4 +146,27 @@ private function timelineBoundary(array $timeline, string $position): ?int
133146

134147
return is_numeric($sequence) ? (int) $sequence : null;
135148
}
149+
150+
private function attributeValue(mixed $model, string $attribute): mixed
151+
{
152+
if (! is_object($model) || ! method_exists($model, 'getAttributes')) {
153+
return null;
154+
}
155+
156+
$attributes = $model->getAttributes();
157+
158+
return $attributes[$attribute] ?? null;
159+
}
160+
161+
private function databaseAttributeValue(mixed $model, string $attribute): mixed
162+
{
163+
if (! $model instanceof Model || ! $model->exists) {
164+
return null;
165+
}
166+
167+
return DB::connection($model->getConnectionName())
168+
->table($model->getTable())
169+
->where($model->getKeyName(), $model->getKey())
170+
->value($attribute);
171+
}
136172
}

tests/Feature/V2DashboardWorkflowTest.php

Lines changed: 104 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1518,6 +1518,110 @@ public function testShowUsesConfiguredSummaryAndHistoryModels(): void
15181518
->assertJsonPath('workflow_definition_fingerprint', 'configured-waterline-fingerprint');
15191519
}
15201520

1521+
public function testShowUsesConfiguredSummaryAndHistoryModelsWhenTypedMemosAreMissing(): void
1522+
{
1523+
config()->set('waterline.engine_source', 'v2');
1524+
config()->set('workflows.v2.run_summary_model', ConfiguredWaterlineDetailRunSummary::class);
1525+
config()->set('workflows.v2.history_event_model', ConfiguredWaterlineDetailHistoryEvent::class);
1526+
1527+
$this->createConfiguredDetailSummaryTable();
1528+
$this->createConfiguredDetailHistoryTable();
1529+
1530+
$instance = WorkflowInstance::create([
1531+
'id' => 'configured-waterline-detail-instance-no-typed-memo',
1532+
'workflow_class' => 'Missing\\ConfiguredWaterlineWorkflow',
1533+
'workflow_type' => 'configured.waterline.workflow',
1534+
'memo' => [
1535+
'customer' => [
1536+
'name' => 'Taylor',
1537+
],
1538+
],
1539+
'run_count' => 1,
1540+
]);
1541+
1542+
$run = WorkflowRun::create([
1543+
'id' => '01JTESTWATERLINECONFIG0002',
1544+
'workflow_instance_id' => $instance->id,
1545+
'run_number' => 1,
1546+
'workflow_class' => 'Missing\\ConfiguredWaterlineWorkflow',
1547+
'workflow_type' => 'configured.waterline.workflow',
1548+
'status' => RunStatus::Waiting->value,
1549+
'memo' => [
1550+
'customer' => [
1551+
'name' => 'Taylor',
1552+
],
1553+
'order' => [
1554+
'id' => 123,
1555+
],
1556+
],
1557+
'search_attributes' => [
1558+
'customer_tier' => 'gold',
1559+
],
1560+
'arguments' => Serializer::serialize([]),
1561+
'connection' => 'redis',
1562+
'queue' => 'default',
1563+
'started_at' => now()->subMinutes(2),
1564+
'last_progress_at' => now()->subMinute(),
1565+
]);
1566+
1567+
$instance->update(['current_run_id' => $run->id]);
1568+
1569+
ConfiguredWaterlineDetailRunSummary::create([
1570+
'id' => $run->id,
1571+
'workflow_instance_id' => $instance->id,
1572+
'run_number' => 1,
1573+
'is_current_run' => true,
1574+
'engine_source' => 'v2',
1575+
'class' => 'Missing\\ConfiguredWaterlineWorkflow',
1576+
'workflow_type' => 'configured.waterline.workflow',
1577+
'business_key' => 'configured-waterline-business',
1578+
'status' => RunStatus::Waiting->value,
1579+
'status_bucket' => 'running',
1580+
'started_at' => $run->started_at,
1581+
'history_event_count' => 1,
1582+
'history_size_bytes' => 128,
1583+
'continue_as_new_recommended' => false,
1584+
'sort_timestamp' => $run->started_at,
1585+
'sort_key' => 'configured-waterline-sort-key',
1586+
'created_at' => $run->started_at,
1587+
'updated_at' => $run->last_progress_at,
1588+
]);
1589+
1590+
ConfiguredWaterlineDetailHistoryEvent::create([
1591+
'id' => (string) Str::ulid(),
1592+
'workflow_run_id' => $run->id,
1593+
'sequence' => 1,
1594+
'event_type' => HistoryEventType::WorkflowStarted->value,
1595+
'payload' => [
1596+
'workflow_class' => 'Missing\\ConfiguredWaterlineWorkflow',
1597+
'workflow_type' => 'configured.waterline.workflow',
1598+
'workflow_definition_fingerprint' => 'configured-waterline-fingerprint',
1599+
'declared_queries' => [],
1600+
'declared_query_contracts' => [],
1601+
'declared_signals' => ['configured-waterline-signal'],
1602+
'declared_signal_contracts' => [],
1603+
'declared_updates' => [],
1604+
'declared_update_contracts' => [],
1605+
'declared_entry_method' => 'handle',
1606+
'declared_entry_mode' => 'canonical',
1607+
'declared_entry_declaring_class' => 'Missing\\ConfiguredWaterlineWorkflow',
1608+
],
1609+
'recorded_at' => $run->started_at,
1610+
]);
1611+
1612+
$this->assertSame(0, WorkflowMemo::query()->count());
1613+
$this->get('/waterline/api/flows/' . $run->id)
1614+
->assertOk()
1615+
->assertJsonPath('status_bucket', 'running')
1616+
->assertJsonPath('business_key', 'configured-waterline-business')
1617+
->assertJsonPath('memo.customer.name', 'Taylor')
1618+
->assertJsonPath('memo.order.id', 123)
1619+
->assertJsonPath('search_attributes.customer_tier', 'gold')
1620+
->assertJsonPath('declared_contract_source', 'durable_history')
1621+
->assertJsonPath('declared_signals.0', 'configured-waterline-signal')
1622+
->assertJsonPath('workflow_definition_fingerprint', 'configured-waterline-fingerprint');
1623+
}
1624+
15211625
public function testShowRebuildsTimelineProjectionRowsOnRead(): void
15221626
{
15231627
config()->set('waterline.engine_source', 'v2');

0 commit comments

Comments
 (0)