Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
36 changes: 36 additions & 0 deletions GUIDE.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ of `@nexus` directives.
- [Error Enums](#error-enums)
- [Output Transforms](#output-transforms)
- [Function References](#function-references)
- [Internal Interfaces](#internal-interfaces)
- [Generation Targets](#generation-targets)
- [Directive Glossary](#directive-glossary)

Expand Down Expand Up @@ -1724,6 +1725,32 @@ descriptor replaces signature-derived typing.

---

## Internal Interfaces

`@nexus.internal` on an interface marks a service that only an SDK calls, such
as Brook's writer. Its package exports nothing, and the SDK calls its modules.

```wit
/// @nexus.service-name "temporal.sdk.streams.v1.StreamWriter"
/// @nexus.internal
interface stream-writer { ... }
```

- Python. The package's `__init__.py` exports nothing. It keeps the operation
registry, where a client looks up serialization contexts. The module names
don't change, since the SDK puts such a package under a private package.
- TypeScript. The package has no `index.ts`, and each declaration is
`@internal`, so `stripInternal` drops it from the published types.
- .NET. Each type is `internal` in place of `public`. The SDK's tests see it
through `InternalsVisibleTo`, or compile their own copy.
- Go. Nothing changes. A caller writes the output under an `internal/`
directory, Go's own rule.
- Java ignores the directive with a warning.

The directive takes no arguments.

---

## Generation Targets

`--targets` sets the code that calls the generated API. Repeat the flag, or
Expand Down Expand Up @@ -2270,6 +2297,15 @@ signal-with-start-workflow: func(...) -> ...;

---

### @nexus.internal

**Placement:** Interface (service) **Syntax:** `@nexus.internal` (no arguments)

Marks a service that only an SDK calls, so its package exports nothing. See
[Internal Interfaces](#internal-interfaces).

---

### @nexus.error

**Placement:** Enum, and each case that gets a class **Syntax:**
Expand Down
2 changes: 2 additions & 0 deletions advanced/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -71,6 +71,8 @@ replaced without deleting these authored helpers.
and priority.
- [`batch-service`](samples/inputs/batch-service.wit): a resource method that
takes its items as arguments and returns one field of the response.
- [`internal-service`](samples/inputs/internal-service.wit): a service that only
an SDK calls, whose package exports nothing.
- [`worker-shutdown`](samples/inputs/worker-shutdown.wit): a proto-backed
request that flattens two fields of one field, and copies sibling fields into
the others.
Expand Down
17 changes: 17 additions & 0 deletions advanced/samples/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,23 @@ returns one field of the response. The field is JSON, so it keeps its absence.
- TypeScript: [`typescript/wit/batch-service/`](typescript/wit/batch-service/),
[`typescript/tests/batch-service.test.ts`](typescript/tests/batch-service.test.ts)

### `internal-service`

A service that only an SDK calls, with `@nexus.internal`. The Python package
exports nothing, TypeScript has no `index.ts` and marks each declaration
`@internal`, and .NET makes each type `internal`. The writer of `stream-writer`
is internal too.

- WIT: [`inputs/internal-service.wit`](inputs/internal-service.wit)
- .NET: [`dotnet/wit/internal-service/`](dotnet/wit/internal-service/),
[`dotnet/tests/GeneratedApiCompileChecks.cs`](dotnet/tests/GeneratedApiCompileChecks.cs)
- Go: [`go/internalservice/`](go/internalservice/)
- Python: [`python/wit/internal_service/`](python/wit/internal_service/),
[`python/tests/test_internal_service.py`](python/tests/test_internal_service.py)
- TypeScript:
[`typescript/wit/internal-service/`](typescript/wit/internal-service/),
[`typescript/tests/internal-service.test.ts`](typescript/tests/internal-service.test.ts)

### `worker-shutdown`

A request that flattens two fields of its worker heartbeat. The call takes the
Expand Down
6 changes: 6 additions & 0 deletions advanced/samples/dotnet/tests/GeneratedApiCompileChecks.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
using System.Threading.Tasks;
using Temporalio.Workflows;
using BatchServiceExample = Nexgen.BatchService;
using InternalServiceExample = Nexgen.InternalService;
using StartWorkflowExample = Nexgen.StartWorkflowService;
using WorkerShutdownExample = Nexgen.WorkerShutdownService;

Expand Down Expand Up @@ -34,6 +35,11 @@ internal static class GeneratedApiCompileChecks
internal static Task<string?> AddItemsAsync() =>
new BatchServiceExample.Batch("b1").AddItemsAsync("x", "y");

// The package is internal, and the tests compile their own copy of it.
internal static Task<InternalServiceExample.FlushResponse> FlushAsync() =>
InternalServiceExample.Operations.FlushAsync(
new InternalServiceExample.FlushOptions("writer-1"));

// The shutdown takes the SDK fields of the heartbeat. The heartbeat copies the worker
// fields of the request.
internal static Task<WorkerShutdownExample.ShutdownWorkerResponse> ShutdownWorkerAsync() =>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@
<Compile Include="../wit/proto-generic/Models.cs" Link="GeneratedProtoGeneric/Models.cs" />
<Compile Include="../wit/stream-service/*.cs" Link="GeneratedStreamService/%(Filename)%(Extension)" />
<Compile Include="../StreamSupport/*.cs" Link="StreamSupport/%(Filename)%(Extension)" />
<!-- The package is internal, so the tests compile their own copy, as an SDK's tests see it. -->
<Compile Include="../wit/internal-service/*.cs" Link="GeneratedInternalService/%(Filename)%(Extension)" />
</ItemGroup>

<ItemGroup>
Expand Down
40 changes: 40 additions & 0 deletions advanced/samples/dotnet/wit/internal-service/Models.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// <auto-generated />
// Generated by nexgen latest. DO NOT EDIT!
#nullable enable

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;

namespace Nexgen.InternalService
{

[GeneratedCode("nexgen", null)]
internal record FlushRequest
{
/// <summary>
/// Initializes a new instance of the <see cref="FlushRequest"/> class.
/// </summary>
public FlushRequest(string writerId)
{
WriterId = writerId;
}

public string WriterId { get; init; }
}

[GeneratedCode("nexgen", null)]
internal record FlushResponse
{
/// <summary>
/// Initializes a new instance of the <see cref="FlushResponse"/> class.
/// </summary>
public FlushResponse(uint flushed)
{
Flushed = flushed;
}

public uint Flushed { get; init; }
}

}
68 changes: 68 additions & 0 deletions advanced/samples/dotnet/wit/internal-service/Operations.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,68 @@
// <auto-generated />
// Generated by nexgen latest. DO NOT EDIT!
#nullable enable

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Threading.Tasks;
using Google.Protobuf.WellKnownTypes;
using Temporalio.Workflows;
using Nexgen.Support;

namespace Nexgen.InternalService
{

/// <summary>
/// Flush one writer. Only an SDK calls it.
/// </summary>
[GeneratedCode("nexgen", null)]
internal class FlushOptions
{
/// <summary>
/// Initializes a new instance of the <see cref="FlushOptions"/> class.
/// </summary>
public FlushOptions(string writerId)
{
WriterId = writerId;
}

public string WriterId { get; set; }
}

/// <summary>
/// Provides generated workflow operation helpers.
/// </summary>
[GeneratedCode("nexgen", null)]
internal static class Operations
{
[GeneratedCode("nexgen", null)]
private const string InternalServiceEndpoint = "internal";

/// <summary>
/// Flush one writer. Only an SDK calls it.
/// </summary>
[GeneratedCode("nexgen", null)]
private static async Task<FlushResponse> FlushAsync(FlushRequest request)
{
var client = Workflow.CreateNexusWorkflowClient<IInternalService>(InternalServiceEndpoint);
var result = await client.ExecuteNexusOperationAsync<FlushResponse>(svc => svc.Flush(request)).ConfigureAwait(true);
return result;
}

/// <summary>
/// Flush one writer. Only an SDK calls it.
/// </summary>
/// <param name="options">Options for the operation.</param>
[GeneratedCode("nexgen", null)]
public static Task<FlushResponse> FlushAsync(FlushOptions options)
{
var request = new FlushRequest(options.WriterId);
return FlushAsync(request);
}

}

}
66 changes: 66 additions & 0 deletions advanced/samples/dotnet/wit/internal-service/Services.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
// <auto-generated />
// Generated by nexgen latest. DO NOT EDIT!
#nullable enable

using System;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.Threading.Tasks;
using NexusRpc;
using Temporalio.Converters;
using Nexgen.Support;

namespace Nexgen.InternalService
{

[GeneratedCode("nexgen", null)]
[NexusService("InternalService")]
internal interface IInternalService
{
/// <summary>
/// Flush one writer. Only an SDK calls it.
/// </summary>
[GeneratedCode("nexgen", null)]
[NexusOperation("Flush")]
FlushResponse Flush(FlushRequest request);

}

internal interface INexgenOperationInfo
{
OperationDefinition Operation { get; }

Func<object, ISerializationContext>? SerializationContext { get; }
}

internal sealed class NexgenOperationInfo<TRequest, TResponse> : INexgenOperationInfo
{
internal NexgenOperationInfo(
OperationDefinition operation,
Func<TRequest, ISerializationContext>? serializationContext = null)
{
Operation = operation;
SerializationContext = serializationContext;
}

internal OperationDefinition Operation { get; }

OperationDefinition INexgenOperationInfo.Operation => Operation;

internal Func<TRequest, ISerializationContext>? SerializationContext { get; }

Func<object, ISerializationContext>? INexgenOperationInfo.SerializationContext => SerializationContext == null ? null : request => SerializationContext((TRequest)request);
}

internal static class NexgenOperationRegistry
{
private static readonly ServiceDefinition InternalServiceServiceDefinition = ServiceDefinition.FromType<IInternalService>();

internal static IReadOnlyDictionary<(string Service, string Operation), INexgenOperationInfo> Operations { get; } = new Dictionary<(string Service, string Operation), INexgenOperationInfo>
{
[("InternalService", "Flush")] = new NexgenOperationInfo<FlushRequest, FlushResponse>(
InternalServiceServiceDefinition.Operations["Flush"]),
};
}

}
Loading
Loading