diff --git a/Directory.Packages.props b/Directory.Packages.props
index e12fc9bfb..1c82cda73 100644
--- a/Directory.Packages.props
+++ b/Directory.Packages.props
@@ -1,7 +1,7 @@
true
- 9.0.0-preview.5.24306.11
+ 9.0.0
8.0.6
7.0.5
6.0.33
@@ -9,7 +9,7 @@
1.6.0
1.8.1
1.8.0-beta.1
- 9.0.0-preview.5.24306.7
+ 9.0.0
6.0.0
@@ -33,7 +33,7 @@
-
+
@@ -65,7 +65,7 @@
-
+
@@ -82,6 +82,7 @@
+
diff --git a/MAINTAINERS.md b/MAINTAINERS.md
index 1155b86fc..4454ee7fb 100644
--- a/MAINTAINERS.md
+++ b/MAINTAINERS.md
@@ -15,9 +15,10 @@ for general contribution guidelines.
- [BrennanConroy](https://github.com/BrennanConroy), Microsoft Corporation
- [davidfowl](https://github.com/davidfowl), Microsoft Corporation
- [JamesNK](https://github.com/JamesNK), Microsoft Corporation
-- [jtattermusch](https://github.com/jtattermusch), Google LLC
- [mgravell](https://github.com/mgravell), Microsoft Corporation
- [ReubenBond](https://github.com/ReubenBond), Microsoft Corporation
+- [stanley-cheung](https://github.com/stanley-cheung), Google LLC
## Emeritus Maintainers (in alphabetical order)
+- [jtattermusch](https://github.com/jtattermusch)
- [JunTaoLuo](https://github.com/JunTaoLuo)
diff --git a/examples/Container/Backend/Dockerfile b/examples/Container/Backend/Dockerfile
index 78b8007d5..7c0429870 100644
--- a/examples/Container/Backend/Dockerfile
+++ b/examples/Container/Backend/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/nightly/sdk:9.0-preview AS build-env
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build-env
WORKDIR /app
# Copy everything
@@ -8,7 +8,7 @@ RUN dotnet restore examples/Container/Backend
RUN dotnet publish examples/Container/Backend -c Release -o out
# Build runtime image
-FROM mcr.microsoft.com/dotnet/nightly/aspnet:9.0-preview
+FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "Backend.dll"]
\ No newline at end of file
diff --git a/examples/Container/Frontend/Dockerfile b/examples/Container/Frontend/Dockerfile
index 23403110c..017712b23 100644
--- a/examples/Container/Frontend/Dockerfile
+++ b/examples/Container/Frontend/Dockerfile
@@ -1,4 +1,4 @@
-FROM mcr.microsoft.com/dotnet/nightly/sdk:9.0-preview AS build-env
+FROM mcr.microsoft.com/dotnet/sdk:9.0 AS build-env
WORKDIR /app
# Copy everything
@@ -8,7 +8,7 @@ RUN dotnet restore examples/Container/Frontend
RUN dotnet publish examples/Container/Frontend -c Release -o out
# Build runtime image
-FROM mcr.microsoft.com/dotnet/nightly/aspnet:9.0-preview
+FROM mcr.microsoft.com/dotnet/aspnet:9.0
WORKDIR /app
COPY --from=build-env /app/out .
ENTRYPOINT ["dotnet", "Frontend.dll"]
\ No newline at end of file
diff --git a/examples/Spar/Server/ClientApp/package-lock.json b/examples/Spar/Server/ClientApp/package-lock.json
index 6215cf0cb..7cf245d58 100644
--- a/examples/Spar/Server/ClientApp/package-lock.json
+++ b/examples/Spar/Server/ClientApp/package-lock.json
@@ -10,7 +10,7 @@
"dependencies": {
"google-protobuf": "^3.19.4",
"grpc-web": "^1.3.1",
- "vue": "^2.6.12",
+ "vue": "^3.0.0",
"vue-class-component": "^7.2.6",
"vue-hot-reload-api": "^2.3.4",
"vue-property-decorator": "^9.1.2"
@@ -420,7 +420,6 @@
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
"integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
- "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -429,7 +428,6 @@
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
"integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -490,7 +488,6 @@
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
"integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
- "dev": true,
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -1690,7 +1687,6 @@
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
- "dev": true,
"dependencies": {
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
@@ -1856,6 +1852,27 @@
"integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==",
"dev": true
},
+ "node_modules/@vue/compiler-core": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.0.tgz",
+ "integrity": "sha512-XqPC7vdv4rFE77S71oCHmT1K4Ks3WE2Gi6Lr4B5wn0Idmp+NyQQBUHsCNieMDRiEpgtJrw+yOHslrsV0AfAsfQ==",
+ "dependencies": {
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "@vue/shared": "3.0.0",
+ "estree-walker": "^2.0.1",
+ "source-map": "^0.6.1"
+ }
+ },
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.0.tgz",
+ "integrity": "sha512-ukDEGOP8P7lCPyStuM3F2iD5w2QPgUu2xwCW2XNeqPjFKIlR2xMsWjy4raI/cLjN6W16GtlMFaZdK8tLj5PRog==",
+ "dependencies": {
+ "@vue/compiler-core": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
+ },
"node_modules/@vue/component-compiler-utils": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz",
@@ -1875,6 +1892,38 @@
"prettier": "^1.18.2 || ^2.0.0"
}
},
+ "node_modules/@vue/reactivity": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.0.tgz",
+ "integrity": "sha512-mEGkztGQrAPZRhV7C6PorrpT3+NtuA4dY2QjMzzrW31noKhssWTajRZTwpLF39NBRrF5UU6cp9+1I0FfavMgEQ==",
+ "dependencies": {
+ "@vue/shared": "3.0.0"
+ }
+ },
+ "node_modules/@vue/runtime-core": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.0.tgz",
+ "integrity": "sha512-3ABMLeA0ZbeVNLbGGLXr+pNUwqXILOqz8WCVGfDWwQb+jW114Cm8djOHVVDoqdvRETQvDf8yHSUmpKHZpQuTkA==",
+ "dependencies": {
+ "@vue/reactivity": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
+ },
+ "node_modules/@vue/runtime-dom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.0.tgz",
+ "integrity": "sha512-f312n5w9gK6mVvkDSj6/Xnot1XjlKXzFBYybmoy6ahAVC8ExbQ+LOWti1IZM/adU8VMNdKaw7Q53Hxz3y5jX8g==",
+ "dependencies": {
+ "@vue/runtime-core": "3.0.0",
+ "@vue/shared": "3.0.0",
+ "csstype": "^2.6.8"
+ }
+ },
+ "node_modules/@vue/shared": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.0.tgz",
+ "integrity": "sha512-4XWL/avABGxU2E2ZF1eZq3Tj7fvksCMssDZUHOykBIMmh5d+KcAnQMC5XHMhtnA0NAvktYsA2YpdsVwVmhWzvA=="
+ },
"node_modules/abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@@ -3485,6 +3534,11 @@
"cssom": "0.3.x"
}
},
+ "node_modules/csstype": {
+ "version": "2.6.21",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
+ "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+ },
"node_modules/dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -3783,9 +3837,9 @@
"dev": true
},
"node_modules/elliptic": {
- "version": "6.5.7",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
- "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
+ "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
"dev": true,
"dependencies": {
"bn.js": "^4.11.9",
@@ -3983,6 +4037,11 @@
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -8161,7 +8220,6 @@
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -8681,7 +8739,6 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
"integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
- "dev": true,
"engines": {
"node": ">=4"
}
@@ -9208,9 +9265,14 @@
"dev": true
},
"node_modules/vue": {
- "version": "2.6.14",
- "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
- "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.0.0.tgz",
+ "integrity": "sha512-ZMrAARZ32sGIaYKr7Fk2GZEBh/VhulSrGxcGBiAvbN4fhjl3tuJyNFbbbLFqGjndbLoBW66I2ECq8ICdvkKdJw==",
+ "dependencies": {
+ "@vue/compiler-dom": "3.0.0",
+ "@vue/runtime-dom": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
},
"node_modules/vue-class-component": {
"version": "7.2.6",
@@ -9691,14 +9753,12 @@
"@babel/helper-string-parser": {
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.22.5.tgz",
- "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==",
- "dev": true
+ "integrity": "sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw=="
},
"@babel/helper-validator-identifier": {
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz",
- "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==",
- "dev": true
+ "integrity": "sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A=="
},
"@babel/helper-validator-option": {
"version": "7.16.7",
@@ -9743,8 +9803,7 @@
"@babel/parser": {
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.0.tgz",
- "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw==",
- "dev": true
+ "integrity": "sha512-vvPKKdMemU85V9WE/l5wZEmImpCtLqbnTvqDS2U1fJ96KrxoW7KrXhNsNCblQlg8Ck4b85yxdTyelsMUgFUXiw=="
},
"@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
"version": "7.16.7",
@@ -10550,7 +10609,6 @@
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/types/-/types-7.23.0.tgz",
"integrity": "sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==",
- "dev": true,
"requires": {
"@babel/helper-string-parser": "^7.22.5",
"@babel/helper-validator-identifier": "^7.22.20",
@@ -10685,6 +10743,27 @@
"integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==",
"dev": true
},
+ "@vue/compiler-core": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.0.0.tgz",
+ "integrity": "sha512-XqPC7vdv4rFE77S71oCHmT1K4Ks3WE2Gi6Lr4B5wn0Idmp+NyQQBUHsCNieMDRiEpgtJrw+yOHslrsV0AfAsfQ==",
+ "requires": {
+ "@babel/parser": "^7.11.5",
+ "@babel/types": "^7.11.5",
+ "@vue/shared": "3.0.0",
+ "estree-walker": "^2.0.1",
+ "source-map": "^0.6.1"
+ }
+ },
+ "@vue/compiler-dom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.0.0.tgz",
+ "integrity": "sha512-ukDEGOP8P7lCPyStuM3F2iD5w2QPgUu2xwCW2XNeqPjFKIlR2xMsWjy4raI/cLjN6W16GtlMFaZdK8tLj5PRog==",
+ "requires": {
+ "@vue/compiler-core": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
+ },
"@vue/component-compiler-utils": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz",
@@ -10702,6 +10781,38 @@
"vue-template-es2015-compiler": "^1.9.0"
}
},
+ "@vue/reactivity": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.0.0.tgz",
+ "integrity": "sha512-mEGkztGQrAPZRhV7C6PorrpT3+NtuA4dY2QjMzzrW31noKhssWTajRZTwpLF39NBRrF5UU6cp9+1I0FfavMgEQ==",
+ "requires": {
+ "@vue/shared": "3.0.0"
+ }
+ },
+ "@vue/runtime-core": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.0.0.tgz",
+ "integrity": "sha512-3ABMLeA0ZbeVNLbGGLXr+pNUwqXILOqz8WCVGfDWwQb+jW114Cm8djOHVVDoqdvRETQvDf8yHSUmpKHZpQuTkA==",
+ "requires": {
+ "@vue/reactivity": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
+ },
+ "@vue/runtime-dom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.0.0.tgz",
+ "integrity": "sha512-f312n5w9gK6mVvkDSj6/Xnot1XjlKXzFBYybmoy6ahAVC8ExbQ+LOWti1IZM/adU8VMNdKaw7Q53Hxz3y5jX8g==",
+ "requires": {
+ "@vue/runtime-core": "3.0.0",
+ "@vue/shared": "3.0.0",
+ "csstype": "^2.6.8"
+ }
+ },
+ "@vue/shared": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.0.0.tgz",
+ "integrity": "sha512-4XWL/avABGxU2E2ZF1eZq3Tj7fvksCMssDZUHOykBIMmh5d+KcAnQMC5XHMhtnA0NAvktYsA2YpdsVwVmhWzvA=="
+ },
"abab": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/abab/-/abab-2.0.5.tgz",
@@ -12046,6 +12157,11 @@
"cssom": "0.3.x"
}
},
+ "csstype": {
+ "version": "2.6.21",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-2.6.21.tgz",
+ "integrity": "sha512-Z1PhmomIfypOpoMjRQB70jfvy/wxT50qW08YXO5lMIJkrdq4yOTR+AW7FqutScmB9NkLwxo+jU+kZLbofZZq/w=="
+ },
"dashdash": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
@@ -12297,9 +12413,9 @@
"dev": true
},
"elliptic": {
- "version": "6.5.7",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.7.tgz",
- "integrity": "sha512-ESVCtTwiA+XhY3wyh24QqRGBoP3rEdDUl3EDUUo9tft074fi19IrdpH7hLCMMP3CIj7jb3W96rn8lt/BqIlt5Q==",
+ "version": "6.6.0",
+ "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.6.0.tgz",
+ "integrity": "sha512-dpwoQcLc/2WLQvJvLRHKZ+f9FgOdjnq11rurqwekGQygGPsYSK29OMMD2WalatiqQ+XGFDglTNixpPfI+lpaAA==",
"dev": true,
"requires": {
"bn.js": "^4.11.9",
@@ -12444,6 +12560,11 @@
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
"dev": true
},
+ "estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w=="
+ },
"esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
@@ -15817,8 +15938,7 @@
"source-map": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
},
"source-map-resolve": {
"version": "0.5.3",
@@ -16233,8 +16353,7 @@
"to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
- "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4=",
- "dev": true
+ "integrity": "sha1-3F5pjL0HkmW8c+A3doGk5Og/YW4="
},
"to-object-path": {
"version": "0.3.0",
@@ -16673,9 +16792,14 @@
"dev": true
},
"vue": {
- "version": "2.6.14",
- "resolved": "https://registry.npmjs.org/vue/-/vue-2.6.14.tgz",
- "integrity": "sha512-x2284lgYvjOMj3Za7kqzRcUSxBboHqtgRE2zlos1qWaOye5yUmHn42LB1250NJBLRwEcdrB0JRwyPTEPhfQjiQ=="
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-3.0.0.tgz",
+ "integrity": "sha512-ZMrAARZ32sGIaYKr7Fk2GZEBh/VhulSrGxcGBiAvbN4fhjl3tuJyNFbbbLFqGjndbLoBW66I2ECq8ICdvkKdJw==",
+ "requires": {
+ "@vue/compiler-dom": "3.0.0",
+ "@vue/runtime-dom": "3.0.0",
+ "@vue/shared": "3.0.0"
+ }
},
"vue-class-component": {
"version": "7.2.6",
diff --git a/examples/Spar/Server/ClientApp/package.json b/examples/Spar/Server/ClientApp/package.json
index f49dbdd08..8c3e8bd7d 100644
--- a/examples/Spar/Server/ClientApp/package.json
+++ b/examples/Spar/Server/ClientApp/package.json
@@ -11,7 +11,7 @@
"dependencies": {
"google-protobuf": "^3.19.4",
"grpc-web": "^1.3.1",
- "vue": "^2.6.12",
+ "vue": "^3.0.0",
"vue-class-component": "^7.2.6",
"vue-hot-reload-api": "^2.3.4",
"vue-property-decorator": "^9.1.2"
diff --git a/global.json b/global.json
index 67d91a4f9..cdbb589ed 100644
--- a/global.json
+++ b/global.json
@@ -1,6 +1,6 @@
{
"sdk": {
- "version": "9.0.100-preview.7.24407.12",
+ "version": "9.0.100",
"rollForward": "latestFeature"
}
}
diff --git a/perf/benchmarkapps/Shared/BenchmarkServiceImpl.cs b/perf/benchmarkapps/Shared/BenchmarkServiceImpl.cs
index 83c03970f..bc8ae2bb9 100644
--- a/perf/benchmarkapps/Shared/BenchmarkServiceImpl.cs
+++ b/perf/benchmarkapps/Shared/BenchmarkServiceImpl.cs
@@ -20,7 +20,7 @@
using Grpc.Core;
using Grpc.Testing;
-class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase
+sealed class BenchmarkServiceImpl : BenchmarkService.BenchmarkServiceBase
{
#if CLIENT_CERTIFICATE_AUTHENTICATION
[Microsoft.AspNetCore.Authorization.Authorize]
@@ -98,4 +98,4 @@ public static SimpleResponse CreateResponse(SimpleRequest request)
var payload = new Payload { Body = body };
return new SimpleResponse { Payload = payload };
}
-}
\ No newline at end of file
+}
diff --git a/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksOptions.cs b/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksOptions.cs
index 84bfe3d91..4390eba2e 100644
--- a/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksOptions.cs
+++ b/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksOptions.cs
@@ -17,6 +17,7 @@
#endregion
using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Hosting;
namespace Grpc.AspNetCore.HealthChecks;
@@ -39,4 +40,21 @@ public sealed class GrpcHealthChecksOptions
/// published by are returned.
///
public bool UseHealthChecksCache { get; set; }
+
+ ///
+ /// Gets or sets a value indicating whether to suppress completing Watch health check calls when the application begins shutting down.
+ /// The default value is false.
+ ///
+ ///
+ ///
+ /// When false, health checks Watch calls are completed with a status of NotServing when the server application begins shutting down.
+ /// Shutdown is indicated by the token being raised and causes Watch to complete.
+ /// When true, health checks Watch calls are left running. Running calls will be eventually be forcefully aborted when the server finishes shutting down.
+ ///
+ ///
+ /// Completing the Watch call allows the server to gracefully exit. If Watch calls aren't shutdown then the server runs until
+ /// is exceeded and the server forcefully aborts remaining active requests.
+ ///
+ ///
+ public bool SuppressCompletionOnShutdown { get; set; }
}
diff --git a/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksPublisher.cs b/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksPublisher.cs
index 7fee5bfe5..24b23031e 100644
--- a/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksPublisher.cs
+++ b/src/Grpc.AspNetCore.HealthChecks/GrpcHealthChecksPublisher.cs
@@ -16,7 +16,6 @@
#endregion
-using System.Linq;
using Grpc.Health.V1;
using Grpc.HealthCheck;
using Microsoft.Extensions.Diagnostics.HealthChecks;
diff --git a/src/Grpc.AspNetCore.HealthChecks/Internal/HealthServiceIntegration.cs b/src/Grpc.AspNetCore.HealthChecks/Internal/HealthServiceIntegration.cs
index fbe185e48..710dccd4b 100644
--- a/src/Grpc.AspNetCore.HealthChecks/Internal/HealthServiceIntegration.cs
+++ b/src/Grpc.AspNetCore.HealthChecks/Internal/HealthServiceIntegration.cs
@@ -22,6 +22,7 @@
using Grpc.HealthCheck;
using Microsoft.AspNetCore.Diagnostics.HealthChecks;
using Microsoft.Extensions.Diagnostics.HealthChecks;
+using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
namespace Grpc.AspNetCore.HealthChecks.Internal;
@@ -32,17 +33,20 @@ internal sealed class HealthServiceIntegration : Grpc.Health.V1.Health.HealthBas
private readonly GrpcHealthChecksOptions _grpcHealthCheckOptions;
private readonly HealthServiceImpl _healthServiceImpl;
private readonly HealthCheckService _healthCheckService;
+ private readonly IHostApplicationLifetime _applicationLifetime;
public HealthServiceIntegration(
HealthServiceImpl healthServiceImpl,
IOptions healthCheckOptions,
IOptions grpcHealthCheckOptions,
- HealthCheckService healthCheckService)
+ HealthCheckService healthCheckService,
+ IHostApplicationLifetime applicationLifetime)
{
_healthCheckOptions = healthCheckOptions.Value;
_grpcHealthCheckOptions = grpcHealthCheckOptions.Value;
_healthServiceImpl = healthServiceImpl;
_healthCheckService = healthCheckService;
+ _applicationLifetime = applicationLifetime;
}
public override Task Check(HealthCheckRequest request, ServerCallContext context)
@@ -57,15 +61,84 @@ public override Task Check(HealthCheckRequest request, Serv
}
}
- public override Task Watch(HealthCheckRequest request, IServerStreamWriter responseStream, ServerCallContext context)
+ public override async Task Watch(HealthCheckRequest request, IServerStreamWriter responseStream, ServerCallContext context)
{
+ ServerCallContext resolvedContext;
+ IServerStreamWriter resolvedResponseStream;
+
+ if (!_grpcHealthCheckOptions.SuppressCompletionOnShutdown)
+ {
+ // Create a linked token source to cancel the request if the application is stopping.
+ // This is required because the server won't shut down gracefully if the request is still open.
+ // The context needs to be wrapped because HealthServiceImpl is in an assembly that can't reference IHostApplicationLifetime.
+ var cts = CancellationTokenSource.CreateLinkedTokenSource(context.CancellationToken, _applicationLifetime.ApplicationStopping);
+ resolvedContext = new WrappedServerCallContext(context, cts);
+ }
+ else
+ {
+ resolvedContext = context;
+ }
+
if (!_grpcHealthCheckOptions.UseHealthChecksCache)
{
// Stream writer replaces first health checks results from the cache with newly calculated health check results.
- responseStream = new WatchServerStreamWriter(this, request, responseStream, context.CancellationToken);
+ resolvedResponseStream = new WatchServerStreamWriter(this, request, responseStream, context.CancellationToken);
+ }
+ else
+ {
+ resolvedResponseStream = responseStream;
+ }
+
+ await _healthServiceImpl.Watch(request, resolvedResponseStream, resolvedContext);
+
+ // If the request is not canceled and the application is stopping then return NotServing before finishing.
+ if (!context.CancellationToken.IsCancellationRequested && _applicationLifetime.ApplicationStopping.IsCancellationRequested)
+ {
+ await responseStream.WriteAsync(new HealthCheckResponse { Status = HealthCheckResponse.Types.ServingStatus.NotServing });
}
+ }
- return _healthServiceImpl.Watch(request, responseStream, context);
+ private sealed class WrappedServerCallContext : ServerCallContext
+ {
+ private readonly ServerCallContext _serverCallContext;
+ private readonly CancellationTokenSource _cancellationTokenSource;
+
+ public WrappedServerCallContext(ServerCallContext serverCallContext, CancellationTokenSource cancellationTokenSource)
+ {
+ _serverCallContext = serverCallContext;
+ _cancellationTokenSource = cancellationTokenSource;
+ }
+
+ protected override string MethodCore => _serverCallContext.Method;
+ protected override string HostCore => _serverCallContext.Host;
+ protected override string PeerCore => _serverCallContext.Peer;
+ protected override DateTime DeadlineCore => _serverCallContext.Deadline;
+ protected override Metadata RequestHeadersCore => _serverCallContext.RequestHeaders;
+ protected override CancellationToken CancellationTokenCore => _cancellationTokenSource.Token;
+ protected override Metadata ResponseTrailersCore => _serverCallContext.ResponseTrailers;
+ protected override Status StatusCore
+ {
+ get => _serverCallContext.Status;
+ set => _serverCallContext.Status = value;
+ }
+ protected override WriteOptions? WriteOptionsCore
+ {
+ get => _serverCallContext.WriteOptions;
+ set => _serverCallContext.WriteOptions = value;
+ }
+ protected override AuthContext AuthContextCore => _serverCallContext.AuthContext;
+
+ protected override IDictionary