# JobStoreContract

> Tracon documentation. Tracon is a .NET package family that adds a control
> plane on Microsoft Agent Framework, published as NuGet packages that run
> inside your own ASP.NET Core application.
>
> Page: https://tracon.dev/api/tracon.testing.contracts.storage.jobstorecontract/
> Summary: JobStoreContract: Behavior tests for the IJobStore contract.

<div class="api-provenance">Namespace Tracon.Testing.Contracts.Storage · Assembly <code>Tracon.Testing.Contracts.Xunit.dll</code></div>

Behavior tests for the [IJobStore](/api/tracon.ijobstore/) contract.

```csharp
public abstract class JobStoreContract : TenantIsolationContract<IJobStore>, IAsyncLifetime, IAsyncDisposable
```

<dl class="api-relations"><dt>Inheritance</dt><dd><a href="https://learn.microsoft.com/dotnet/api/system.object">object</a> ← <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/">StoreCancellationContract&lt;IJobStore&gt;</a> ← <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/">TenantIsolationContract&lt;IJobStore&gt;</a> ← <a href="/api/tracon.testing.contracts.storage.jobstorecontract/">JobStoreContract</a></dd><dt>Implements</dt><dd>IAsyncLifetime, <a href="https://learn.microsoft.com/dotnet/api/system.iasyncdisposable">IAsyncDisposable</a></dd><dt>Inherited Members</dt><dd><a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_TenantA">TenantIsolationContract&lt;IJobStore&gt;.TenantA</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_TenantB">TenantIsolationContract&lt;IJobStore&gt;.TenantB</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_UseAmbientTenant_Tracon_Testing_Contracts_Storage_MutableTenantContext_">TenantIsolationContract&lt;IJobStore&gt;.UseAmbientTenant(MutableTenantContext)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_SeedAsync_System_String_System_String_System_Threading_CancellationToken_">TenantIsolationContract&lt;IJobStore&gt;.SeedAsync(string, string, CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_ExistsAsync_System_String_System_Object_">TenantIsolationContract&lt;IJobStore&gt;.ExistsAsync(string, object)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_CountAsync_System_String_System_Threading_CancellationToken_">TenantIsolationContract&lt;IJobStore&gt;.CountAsync(string, CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_TryDeleteAsync_System_String_System_Object_">TenantIsolationContract&lt;IJobStore&gt;.TryDeleteAsync(string, object)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_TryOverwriteAsync_System_String_System_String_">TenantIsolationContract&lt;IJobStore&gt;.TryOverwriteAsync(string, string)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_CancellableReadAsync_System_Threading_CancellationToken_">TenantIsolationContract&lt;IJobStore&gt;.CancellableReadAsync(CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_CancellableWriteAsync_System_Threading_CancellationToken_">TenantIsolationContract&lt;IJobStore&gt;.CancellableWriteAsync(CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_WroteAnythingAsync">TenantIsolationContract&lt;IJobStore&gt;.WroteAnythingAsync()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_Tenant_cannot_read_another_tenants_record">TenantIsolationContract&lt;IJobStore&gt;.Tenant_cannot_read_another_tenants_record()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_Tenant_reads_its_own_record">TenantIsolationContract&lt;IJobStore&gt;.Tenant_reads_its_own_record()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_Tenant_does_not_see_another_tenants_record_in_the_list">TenantIsolationContract&lt;IJobStore&gt;.Tenant_does_not_see_another_tenants_record_in_the_list()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_Tenant_cannot_delete_another_tenants_record">TenantIsolationContract&lt;IJobStore&gt;.Tenant_cannot_delete_another_tenants_record()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_Same_name_lives_independently_across_two_tenants">TenantIsolationContract&lt;IJobStore&gt;.Same_name_lives_independently_across_two_tenants()</a>, <a href="/api/tracon.testing.contracts.storage.tenantisolationcontract-1/#Tracon_Testing_Contracts_Storage_TenantIsolationContract_1_AmbientTenant">TenantIsolationContract&lt;IJobStore&gt;.AmbientTenant</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_CreateStoreAsync">StoreCancellationContract&lt;IJobStore&gt;.CreateStoreAsync()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_InitializeAsync">StoreCancellationContract&lt;IJobStore&gt;.InitializeAsync()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_DisposeAsync">StoreCancellationContract&lt;IJobStore&gt;.DisposeAsync()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_OnDisposeAsync">StoreCancellationContract&lt;IJobStore&gt;.OnDisposeAsync()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_CancellableReadAsync_System_Threading_CancellationToken_">StoreCancellationContract&lt;IJobStore&gt;.CancellableReadAsync(CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_CancellableWriteAsync_System_Threading_CancellationToken_">StoreCancellationContract&lt;IJobStore&gt;.CancellableWriteAsync(CancellationToken)</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_WroteAnythingAsync">StoreCancellationContract&lt;IJobStore&gt;.WroteAnythingAsync()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_Canceled_token_throws_on_read">StoreCancellationContract&lt;IJobStore&gt;.Canceled_token_throws_on_read()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_The_write_this_contract_checks_can_be_read_back">StoreCancellationContract&lt;IJobStore&gt;.The_write_this_contract_checks_can_be_read_back()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_Canceled_token_throws_on_write_and_leaves_no_trace">StoreCancellationContract&lt;IJobStore&gt;.Canceled_token_throws_on_write_and_leaves_no_trace()</a>, <a href="/api/tracon.testing.contracts.storage.storecancellationcontract-1/#Tracon_Testing_Contracts_Storage_StoreCancellationContract_1_Store">StoreCancellationContract&lt;IJobStore&gt;.Store</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gettype">object.GetType()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.memberwiseclone">object.MemberwiseClone()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.tostring">object.ToString()</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object)">object.Equals(object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.equals#system-object-equals(system-object-system-object)">object.Equals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.referenceequals">object.ReferenceEquals(object?, object?)</a>, <a href="https://learn.microsoft.com/dotnet/api/system.object.gethashcode">object.GetHashCode()</a></dd></dl>

## Remarks

The in-memory store and the PostgreSQL store must pass the same
scenarios. The lease-expiry test runs against real time (a short lease +
a short wait): the PostgreSQL implementation does not take its clock
through an injectable [TimeProvider](https://learn.microsoft.com/dotnet/api/system.timeprovider), so fake time cannot be
used here.

## Constructors

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract__ctor"></a> JobStoreContract\(\)

```csharp
protected JobStoreContract()
```

## Methods

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_cancelled_job_is_changed_by_neither_completion_nor_release"></a> A\_cancelled\_job\_is\_changed\_by\_neither\_completion\_nor\_release\(\)

```csharp
[Fact]
public Task A_cancelled_job_is_changed_by_neither_completion_nor_release()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_finished_job_is_not_finalized_a_second_time"></a> A\_finished\_job\_is\_not\_finalized\_a\_second\_time\(\)

```csharp
[Fact]
public Task A_finished_job_is_not_finalized_a_second_time()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_job_without_a_time_limit_reads_back_none"></a> A\_job\_without\_a\_time\_limit\_reads\_back\_none\(\)

```csharp
[Fact]
public Task A_job_without_a_time_limit_reads_back_none()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_jobs_own_time_limit_survives_the_round_trip_and_the_lease"></a> A\_jobs\_own\_time\_limit\_survives\_the\_round\_trip\_and\_the\_lease\(\)

```csharp
[Fact]
public Task A_jobs_own_time_limit_survives_the_round_trip_and_the_lease()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_jobs_time_limit_beyond_an_int_of_milliseconds_survives_the_round_trip_and_the_lease"></a> A\_jobs\_time\_limit\_beyond\_an\_int\_of\_milliseconds\_survives\_the\_round\_trip\_and\_the\_lease\(\)

```csharp
[Fact]
public Task A_jobs_time_limit_beyond_an_int_of_milliseconds_survives_the_round_trip_and_the_lease()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_pending_report_marks_the_item_and_counts_nothing"></a> A\_pending\_report\_marks\_the\_item\_and\_counts\_nothing\(\)

A pending report marks the item with the run that is processing it and
counts nothing; the report that finishes the item is counted once.

```csharp
[Fact]
public Task A_pending_report_marks_the_item_and_counts_nothing()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

#### Remarks

Workflow recovery writes the run id on the item BEFORE the run starts, so a
job leased again after a crash finds the run the item was processing. A
store that counted the marker, or finished the item on it, would close the
job as done while its work was still in flight.

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_A_report_for_a_finished_item_changes_nothing"></a> A\_report\_for\_a\_finished\_item\_changes\_nothing\(\)

A report for an item that already finished changes neither the item nor
the counters.

```csharp
[Fact]
public Task A_report_for_a_finished_item_changes_nothing()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

#### Remarks

The SQL stores update an item only while it is pending. A store that
overwrote a finished item let a late report from a worker whose lease had
expired rewrite the result the job already gave, and a marker written
after the item finished would turn it back into a pending item.

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_An_id_that_is_already_queued_is_refused_and_the_queued_job_is_kept"></a> An\_id\_that\_is\_already\_queued\_is\_refused\_and\_the\_queued\_job\_is\_kept\(\)

```csharp
[Fact]
public Task An_id_that_is_already_queued_is_refused_and_the_queued_job_is_kept()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_CancelAsync_does_not_affect_another_tenants_job"></a> CancelAsync\_does\_not\_affect\_another\_tenants\_job\(\)

```csharp
[Fact]
public Task CancelAsync_does_not_affect_another_tenants_job()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_CancelAsync_works_only_in_eligible_states_Tracon_JobStatus_System_Boolean_"></a> CancelAsync\_works\_only\_in\_eligible\_states\(JobStatus, bool\)

```csharp
[Theory]
[InlineData(new object?[] { JobStatus.Pending, true })]
[InlineData(new object?[] { JobStatus.Completed, false })]
[InlineData(new object?[] { JobStatus.Failed, false })]
public Task CancelAsync_works_only_in_eligible_states(JobStatus status, bool expected)
```

#### Parameters

`status` [JobStatus](/api/tracon.jobstatus/)

`expected` [bool](https://learn.microsoft.com/dotnet/api/system.boolean)

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_CompleteAsync_releases_the_lease"></a> CompleteAsync\_releases\_the\_lease\(\)

```csharp
[Fact]
public Task CompleteAsync_releases_the_lease()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_CountAsync_System_String_System_Threading_CancellationToken_"></a> CountAsync\(string, CancellationToken\)

Reports how many records the given tenant sees through the listing endpoint.

```csharp
protected override ValueTask<int> CountAsync(string tenantId, CancellationToken cancellationToken)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The reading tenant.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The token every store call inside the hook must be handed; see
[TenantIsolationContract.SeedAsync](/api/tracon.testing.contracts.storage/).

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[int](https://learn.microsoft.com/dotnet/api/system.int32)\>

The number of records seen.

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Enqueued_job_defaults_to_the_default_lane"></a> Enqueued\_job\_defaults\_to\_the\_default\_lane\(\)

```csharp
[Fact]
public Task Enqueued_job_defaults_to_the_default_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Enqueued_job_starts_pending_and_creates_items"></a> Enqueued\_job\_starts\_pending\_and\_creates\_items\(\)

```csharp
[Fact]
public Task Enqueued_job_starts_pending_and_creates_items()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_ExistsAsync_System_String_System_Object_"></a> ExistsAsync\(string, object\)

Reports whether the record is visible from the given tenant's viewpoint.

```csharp
protected override ValueTask<bool> ExistsAsync(string tenantId, object key)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The reading tenant.

`key` [object](https://learn.microsoft.com/dotnet/api/system.object)

The key returned by [TenantIsolationContract.SeedAsync](/api/tracon.testing.contracts.storage/).

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[bool](https://learn.microsoft.com/dotnet/api/system.boolean)\>

[true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) if the record is visible.

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_GetAsync_returns_null_for_another_tenant"></a> GetAsync\_returns\_null\_for\_another\_tenant\(\)

```csharp
[Fact]
public Task GetAsync_returns_null_for_another_tenant()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Job_can_be_re_leased_once_the_lease_expires"></a> Job\_can\_be\_re\_leased\_once\_the\_lease\_expires\(\)

```csharp
[Fact]
public Task Job_can_be_re_leased_once_the_lease_expires()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Job_not_yet_due_cannot_be_leased"></a> Job\_not\_yet\_due\_cannot\_be\_leased\(\)

```csharp
[Fact]
public Task Job_not_yet_due_cannot_be_leased()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_lane_filter_never_returns_a_job_from_an_unlisted_lane"></a> Lease\_with\_a\_lane\_filter\_never\_returns\_a\_job\_from\_an\_unlisted\_lane\(\)

```csharp
[Fact]
public Task Lease_with_a_lane_filter_never_returns_a_job_from_an_unlisted_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_lane_filter_only_returns_a_job_in_that_lane"></a> Lease\_with\_a\_lane\_filter\_only\_returns\_a\_job\_in\_that\_lane\(\)

```csharp
[Fact]
public Task Lease_with_a_lane_filter_only_returns_a_job_in_that_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_counts_a_running_job"></a> Lease\_with\_a\_tenant\_cap\_counts\_a\_running\_job\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_counts_a_running_job()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_counts_both_workflow_handler_keys_together"></a> Lease\_with\_a\_tenant\_cap\_counts\_both\_workflow\_handler\_keys\_together\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_counts_both_workflow_handler_keys_together()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_does_not_count_a_job_of_another_handler_key"></a> Lease\_with\_a\_tenant\_cap\_does\_not\_count\_a\_job\_of\_another\_handler\_key\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_does_not_count_a_job_of_another_handler_key()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_does_not_count_a_lease_that_has_expired"></a> Lease\_with\_a\_tenant\_cap\_does\_not\_count\_a\_lease\_that\_has\_expired\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_does_not_count_a_lease_that_has_expired()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_does_not_count_the_leases_of_another_tenant"></a> Lease\_with\_a\_tenant\_cap\_does\_not\_count\_the\_leases\_of\_another\_tenant\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_does_not_count_the_leases_of_another_tenant()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_leases_up_to_the_cap_for_one_tenant"></a> Lease\_with\_a\_tenant\_cap\_leases\_up\_to\_the\_cap\_for\_one\_tenant\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_leases_up_to_the_cap_for_one_tenant()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_skips_a_tenant_at_the_cap_and_leases_the_oldest_job_of_another"></a> Lease\_with\_a\_tenant\_cap\_skips\_a\_tenant\_at\_the\_cap\_and\_leases\_the\_oldest\_job\_of\_another\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_skips_a_tenant_at_the_cap_and_leases_the_oldest_job_of_another()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_still_honors_the_lane_filter"></a> Lease\_with\_a\_tenant\_cap\_still\_honors\_the\_lane\_filter\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_still_honors_the_lane_filter()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_still_leases_a_job_of_another_handler_key_of_a_tenant_at_the_cap"></a> Lease\_with\_a\_tenant\_cap\_still\_leases\_a\_job\_of\_another\_handler\_key\_of\_a\_tenant\_at\_the\_cap\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_still_leases_a_job_of_another_handler_key_of_a_tenant_at_the_cap()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_a_tenant_cap_that_names_no_handler_key_or_no_room_is_refused"></a> Lease\_with\_a\_tenant\_cap\_that\_names\_no\_handler\_key\_or\_no\_room\_is\_refused\(\)

```csharp
[Fact]
public Task Lease_with_a_tenant_cap_that_names_no_handler_key_or_no_room_is_refused()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_an_empty_lanes_list_applies_no_filter"></a> Lease\_with\_an\_empty\_lanes\_list\_applies\_no\_filter\(\)

```csharp
[Fact]
public Task Lease_with_an_empty_lanes_list_applies_no_filter()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_with_null_lanes_applies_no_filter"></a> Lease\_with\_null\_lanes\_applies\_no\_filter\(\)

```csharp
[Fact]
public Task Lease_with_null_lanes_applies_no_filter()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Lease_without_a_tenant_cap_gives_one_tenant_the_whole_queue_in_age_order"></a> Lease\_without\_a\_tenant\_cap\_gives\_one\_tenant\_the\_whole\_queue\_in\_age\_order\(\)

```csharp
[Fact]
public Task Lease_without_a_tenant_cap_gives_one_tenant_the_whole_queue_in_age_order()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Leased_job_is_not_given_to_another_worker_before_expiry"></a> Leased\_job\_is\_not\_given\_to\_another\_worker\_before\_expiry\(\)

```csharp
[Fact]
public Task Leased_job_is_not_given_to_another_worker_before_expiry()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Leasing_marks_Leased_and_increments_the_attempt"></a> Leasing\_marks\_Leased\_and\_increments\_the\_attempt\(\)

```csharp
[Fact]
public Task Leasing_marks_Leased_and_increments_the_attempt()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_MarkRunningAsync_works_only_for_the_real_owner"></a> MarkRunningAsync\_works\_only\_for\_the\_real\_owner\(\)

```csharp
[Fact]
public Task MarkRunningAsync_works_only_for_the_real_owner()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_filters_by_handler_key"></a> QueryAsync\_filters\_by\_handler\_key\(\)

```csharp
[Fact]
public Task QueryAsync_filters_by_handler_key()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_filters_by_lane"></a> QueryAsync\_filters\_by\_lane\(\)

```csharp
[Fact]
public Task QueryAsync_filters_by_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_filters_by_tenant"></a> QueryAsync\_filters\_by\_tenant\(\)

```csharp
[Fact]
public Task QueryAsync_filters_by_tenant()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_lane_filter_does_not_leak_another_tenants_job"></a> QueryAsync\_lane\_filter\_does\_not\_leak\_another\_tenants\_job\(\)

```csharp
[Fact]
public Task QueryAsync_lane_filter_does_not_leak_another_tenants_job()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_returns_nothing_for_a_handler_key_no_job_uses"></a> QueryAsync\_returns\_nothing\_for\_a\_handler\_key\_no\_job\_uses\(\)

```csharp
[Fact]
public Task QueryAsync_returns_nothing_for_a_handler_key_no_job_uses()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_QueryAsync_treats_an_empty_handler_key_as_a_filter_that_matches_nothing"></a> QueryAsync\_treats\_an\_empty\_handler\_key\_as\_a\_filter\_that\_matches\_nothing\(\)

```csharp
[Fact]
public Task QueryAsync_treats_an_empty_handler_key_as_a_filter_that_matches_nothing()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_counts_a_job_released_for_retry_as_pending_again"></a> Queue\_depth\_counts\_a\_job\_released\_for\_retry\_as\_pending\_again\(\)

```csharp
[Fact]
public Task Queue_depth_counts_a_job_released_for_retry_as_pending_again()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_counts_every_tenants_jobs_together"></a> Queue\_depth\_counts\_every\_tenants\_jobs\_together\(\)

```csharp
[Fact]
public Task Queue_depth_counts_every_tenants_jobs_together()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_drops_a_lane_once_its_last_job_finishes"></a> Queue\_depth\_drops\_a\_lane\_once\_its\_last\_job\_finishes\(\)

```csharp
[Fact]
public Task Queue_depth_drops_a_lane_once_its_last_job_finishes()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_groups_pending_jobs_by_lane"></a> Queue\_depth\_groups\_pending\_jobs\_by\_lane\(\)

```csharp
[Fact]
public Task Queue_depth_groups_pending_jobs_by_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_is_empty_when_no_job_is_open"></a> Queue\_depth\_is\_empty\_when\_no\_job\_is\_open\(\)

```csharp
[Fact]
public Task Queue_depth_is_empty_when_no_job_is_open()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_never_counts_a_terminal_status"></a> Queue\_depth\_never\_counts\_a\_terminal\_status\(\)

```csharp
[Fact]
public Task Queue_depth_never_counts_a_terminal_status()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Queue_depth_separates_the_open_statuses"></a> Queue\_depth\_separates\_the\_open\_statuses\(\)

```csharp
[Fact]
public Task Queue_depth_separates_the_open_statuses()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_ReleaseForRetryAsync_returns_to_pending_without_resetting_the_attempt"></a> ReleaseForRetryAsync\_returns\_to\_pending\_without\_resetting\_the\_attempt\(\)

```csharp
[Fact]
public Task ReleaseForRetryAsync_returns_to_pending_without_resetting_the_attempt()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_ReportItemAsync_counts_successful_and_failed_items_separately"></a> ReportItemAsync\_counts\_successful\_and\_failed\_items\_separately\(\)

```csharp
[Fact]
public Task ReportItemAsync_counts_successful_and_failed_items_separately()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_ReportItemAsync_is_idempotent"></a> ReportItemAsync\_is\_idempotent\(\)

```csharp
[Fact]
public Task ReportItemAsync_is_idempotent()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_Retry_preserves_the_jobs_lane"></a> Retry\_preserves\_the\_jobs\_lane\(\)

```csharp
[Fact]
public Task Retry_preserves_the_jobs_lane()
```

#### Returns

 [Task](https://learn.microsoft.com/dotnet/api/system.threading.tasks.task)

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_SeedAsync_System_String_System_String_System_Threading_CancellationToken_"></a> SeedAsync\(string, string, CancellationToken\)

Writes a sample record for the given tenant.

```csharp
protected override ValueTask<object> SeedAsync(string tenantId, string name, CancellationToken cancellationToken)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The tenant that owns the record.

`name` [string](https://learn.microsoft.com/dotnet/api/system.string)

The name distinguishing the record. The same name may be used by two tenants.

`cancellationToken` [CancellationToken](https://learn.microsoft.com/dotnet/api/system.threading.cancellationtoken)

The token every store call inside the hook must be handed. The
cancellation contract calls this hook with a token that is already
cancelled, so a hook that drops the token reports a store as sound
when it is not.

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[object](https://learn.microsoft.com/dotnet/api/system.object)\>

The key to use for reading the record back.

### <a id="Tracon_Testing_Contracts_Storage_JobStoreContract_TryDeleteAsync_System_String_System_Object_"></a> TryDeleteAsync\(string, object\)

Attempts to delete the record on behalf of the given tenant.

```csharp
protected override ValueTask<bool?> TryDeleteAsync(string tenantId, object key)
```

#### Parameters

`tenantId` [string](https://learn.microsoft.com/dotnet/api/system.string)

The tenant attempting the delete.

`key` [object](https://learn.microsoft.com/dotnet/api/system.object)

The key returned by [TenantIsolationContract.SeedAsync](/api/tracon.testing.contracts.storage/).

#### Returns

 [ValueTask](https://learn.microsoft.com/dotnet/api/system.threading.tasks.valuetask\-1)<[bool](https://learn.microsoft.com/dotnet/api/system.boolean)?\>

[true](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool) if the delete succeeded, [false](https://learn.microsoft.com/dotnet/csharp/language-reference/builtin-types/bool)
if the record was not found; [null](https://learn.microsoft.com/dotnet/csharp/language-reference/keywords/null) if the store does
not offer deletion.

#### Remarks

There is no delete in the job queue; the only destructive operation
available to a tenant is cancel.
