Prechádzať zdrojové kódy

Add a 'Hello, World' tutorial (#2023)

Motivation:

Tutorials are a great way to introduce new users to the library.

Modifications:

- Add a 'hello, world' tutorial

Result:

Easier to get started
George Barnett 1 rok pred
rodič
commit
ad52f944b2
17 zmenil súbory, kde vykonal 224 pridanie a 1 odobranie
  1. 1 1
      .spi.yml
  2. 1 0
      Examples/v2/hello-world/HelloWorld.proto
  3. 4 0
      Sources/GRPCCore/Documentation.docc/Documentation.md
  4. 129 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial
  5. 1 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec02-step01.txt
  6. 1 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec02-step02.txt
  7. 15 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec03-step01.proto
  8. 17 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec03-step02.proto
  9. 10 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step01.swift
  10. 19 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step02.swift
  11. 3 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step03.swift
  12. 6 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step04.swift
  13. 1 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step05.txt
  14. 2 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step06.txt
  15. BIN
      Sources/GRPCCore/Documentation.docc/Tutorials/Resources/image.png
  16. 13 0
      Sources/GRPCCore/Documentation.docc/Tutorials/Table-of-Contents.tutorial
  17. 1 0
      scripts/license-check.sh

+ 1 - 1
.spi.yml

@@ -1,5 +1,5 @@
 version: 1
 builder:
   configs:
-    - documentation_targets: [GRPC, GRPCReflectionService, protoc-gen-grpc-swift, _GRPCCore]
+    - documentation_targets: [GRPC, GRPCReflectionService, protoc-gen-grpc-swift, GRPCCore]
       swift_version: 6.0

+ 1 - 0
Examples/v2/hello-world/HelloWorld.proto

@@ -0,0 +1 @@
+../../../Protos/upstream/grpc/examples/helloworld.proto

+ 4 - 0
Sources/GRPCCore/Documentation.docc/Documentation.md

@@ -21,6 +21,10 @@ contains products of this package:
 
 ## Topics
 
+### Tutorials
+
+- <doc:Hello-World>
+
 ### Getting involved
 
 Resources for developers working on gRPC Swift:

+ 129 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Hello-World.tutorial

@@ -0,0 +1,129 @@
+@Tutorial(time: 10) {
+  @XcodeRequirement(
+    title: "Xcode 16 Beta 5+",
+    destination: "https://developer.apple.com/download/"
+  )
+
+  @Intro(title: "Quick Start: Hello, World!") {
+    This tutorial walks you through the canonical "Hello, World!" program for gRPC Swift. You'll
+    learn how to implement a service using generated stubs, then you'll learn to configure and use
+    a gRPC server. You'll also see how to create a client and use it to call the server.
+
+    The tutorial assumes you are comfortable with both Swift and the basic concepts of gRPC. If you
+    aren't then check out the Swift [Getting Started](https://www.swift.org/getting-started/) guide
+    and the [gRPC website](https://grpc.io) for more information.
+
+    You'll need a local copy of the example code to work through this tutorial. Download the example
+    code from our GitHub repository if you haven't done so already. You can do this by cloning the
+    repository by running the following command in a terminal:
+
+    ```console
+    git clone https://github.com/grpc/grpc-swift
+    ```
+
+    The rest of the tutorial assumes that your current working directory is the cloned `grpc-swift`
+    directory.
+  }
+
+  @Section(title: "Run a gRPC application") {
+    Let's start by running the existing Greeter application.
+
+    @Steps {
+      @Step {
+        In a terminal run `swift run hello-world serve` to start the server. By default it'll start
+        listening on port 31415.
+
+        @Code(name: "Console.txt", file: "hello-world-sec02-step01.txt")
+      }
+
+      @Step {
+        In another terminal run `swift run hello-world greet` to create a client, connect
+        to the server you started and send it a request and print the response.
+
+        @Code(name: "Console.txt", file: "hello-world-sec02-step02.txt")
+      }
+
+      @Step {
+        Congratulations! You've just run a client-server application with gRPC Swift. You can now
+        cancel the two running processes.
+      }
+    }
+  }
+
+  @Section(title: "Update a gRPC service") {
+    Now let's look at how to update the application with an extra method on the server for the
+    client to call. Our gRPC service is defined using protocol buffers; you can find out lots more
+    about how to define a service in a `.proto` file in [What is gRPC?](https://grpc.io/docs/what-is-grpc/).
+    For now all you need to know is that both the server and client "stub" have a `SayHello` RPC
+    method that takes a `HelloRequest` parameter from the client and returns a `HelloReply` from
+    the server.
+
+    @Steps {
+      @Step {
+        Open `HelloWorld.proto` in the `Examples/v2/hello-world` directory to see how the
+        service is defined.
+
+        @Code(name: "HelloWorld.proto", file: "hello-world-sec03-step01.proto")
+      }
+
+      @Step {
+        Let's update it so that the `Greeter` service has two methods. Add a  new `SayHelloAgain`
+        method, with the same request and response types.
+
+        @Code(name: "HelloWorld.proto", file: "hello-world-sec03-step02.proto")
+      }
+    }
+  }
+
+  @Section(title: "Update and run the application") {
+    You need to regenerate the stubs as the service definition has changed. To do this run the
+    following command from the root of the checked out repository:
+
+    ```console
+    Protos/generate.sh
+    ```
+
+    You'll learn how to do this manually in another tutorial. Now that the stubs have been updated
+    you need to implement and call the new method in the human-written parts of your application.
+
+    @Steps {
+      @Step {
+        Open `Serve.swift` in the `Examples/v2/hello-world/Subcommands` directory.
+
+        @Code(name: "Serve.swift", file: "hello-world-sec04-step01.swift")
+      }
+
+      @Step {
+        Implement the new method like this:
+
+        @Code(name: "Serve.swift", file: "hello-world-sec04-step02.swift")
+      }
+
+      @Step {
+        Let's update the client now. Open `Greet.swift` in the
+        `Examples/v2/hello-world/Subcommands` directory.
+
+        @Code(name: "Greet.swift", file: "hello-world-sec04-step03.swift")
+      }
+
+      @Step {
+        Add a call to the `sayHelloAgain` method:
+
+        @Code(name: "Greet.swift", file: "hello-world-sec04-step04.swift")
+      }
+
+      @Step {
+        Just like we did before, open a terminal and start the server by
+        running `swift run hello-world serve`
+
+        @Code(name: "Console.txt", file: "hello-world-sec04-step05.txt")
+      }
+
+      @Step {
+        In a separate terminal run `swift run hello-world greet` to call the server.
+
+        @Code(name: "Console.txt", file: "hello-world-sec04-step06.txt")
+      }
+    }
+  }
+}

+ 1 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec02-step01.txt

@@ -0,0 +1 @@
+Greeter listening on [ipv4]127.0.0.1:31415

+ 1 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec02-step02.txt

@@ -0,0 +1 @@
+Hello, stranger

+ 15 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec03-step01.proto

@@ -0,0 +1,15 @@
+// The greeting service definition.
+service Greeter {
+  // Sends a greeting.
+  rpc SayHello (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+  string name = 1;
+}
+
+// The response message containing the greetings.
+message HelloReply {
+  string message = 1;
+}

+ 17 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec03-step02.proto

@@ -0,0 +1,17 @@
+// The greeting service definition.
+service Greeter {
+  // Sends a greeting.
+  rpc SayHello (HelloRequest) returns (HelloReply) {}
+  // Sends another greeting.
+  rpc SayHelloAgain (HelloRequest) returns (HelloReply) {}
+}
+
+// The request message containing the user's name.
+message HelloRequest {
+  string name = 1;
+}
+
+// The response message containing the greetings.
+message HelloReply {
+  string message = 1;
+}

+ 10 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step01.swift

@@ -0,0 +1,10 @@
+struct Greeter: Helloworld_GreeterServiceProtocol {
+  func sayHello(
+    request: ServerRequest.Single<Helloworld_HelloRequest>
+  ) async throws -> ServerResponse.Single<Helloworld_HelloReply> {
+    var reply = Helloworld_HelloReply()
+    let recipient = request.message.name.isEmpty ? "stranger" : request.message.name
+    reply.message = "Hello, \(recipient)"
+    return ServerResponse.Single(message: reply)
+  }
+}

+ 19 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step02.swift

@@ -0,0 +1,19 @@
+struct Greeter: Helloworld_GreeterServiceProtocol {
+  func sayHello(
+    request: ServerRequest.Single<Helloworld_HelloRequest>
+  ) async throws -> ServerResponse.Single<Helloworld_HelloReply> {
+    var reply = Helloworld_HelloReply()
+    let recipient = request.message.name.isEmpty ? "stranger" : request.message.name
+    reply.message = "Hello, \(recipient)"
+    return ServerResponse.Single(message: reply)
+  }
+
+  func sayHelloAgain(
+    request: ServerRequest.Single<Helloworld_HelloRequest>
+  ) async throws -> ServerResponse.Single<Helloworld_HelloReply> {
+    var reply = Helloworld_HelloReply()
+    let recipient = request.message.name.isEmpty ? "stranger" : request.message.name
+    reply.message = "Hello again, \(recipient)"
+    return ServerResponse.Single(message: reply)
+  }
+}

+ 3 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step03.swift

@@ -0,0 +1,3 @@
+let greeter = Helloworld_GreeterClient(wrapping: client)
+let reply = try await greeter.sayHello(.with { $0.name = self.name })
+print(reply.message)

+ 6 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step04.swift

@@ -0,0 +1,6 @@
+let greeter = Helloworld_GreeterClient(wrapping: client)
+let reply = try await greeter.sayHello(.with { $0.name = self.name })
+print(reply.message)
+
+let replyAgain = try await greeter.sayHelloAgain(.with { $0.name = self.name })
+print(replyAgain.message)

+ 1 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step05.txt

@@ -0,0 +1 @@
+Greeter listening on [ipv4]127.0.0.1:31415

+ 2 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Hello-World/Resources/hello-world-sec04-step06.txt

@@ -0,0 +1,2 @@
+Hello, stranger
+Hello again, stranger

BIN
Sources/GRPCCore/Documentation.docc/Tutorials/Resources/image.png


+ 13 - 0
Sources/GRPCCore/Documentation.docc/Tutorials/Table-of-Contents.tutorial

@@ -0,0 +1,13 @@
+@Tutorials(name: "gRPC Swift") {
+  @Intro(title: "Working with gRPC Swift") {
+    Learn how to use gRPC Swift to implement gRPC services and call them using generated clients.
+  }
+
+  @Chapter(name: "Quick Start") {
+    Follow this "Hello World" tutorial for a quick start with gRPC Swift.
+
+    @Image(source: "image.png")
+
+    @TutorialReference(tutorial: "doc:Hello-World")
+  }
+}

+ 1 - 0
scripts/license-check.sh

@@ -107,6 +107,7 @@ check_copyright_headers() {
     ! -name '*.grpc.swift' \
     ! -name 'LinuxMain.swift' \
     ! -name 'XCTestManifests.swift' \
+    ! -path './Sources/GRPCCore/Documentation.docc/*' \
     ! -path './FuzzTesting/.build/*' \
     ! -path './Performance/QPSBenchmark/.build/*' \
     ! -path './Performance/Benchmarks/.build/*' \