Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

EES-4535 Update Data.Processor, Notifier and Publisher function apps to run in Isolated Worker model #4673

Merged

Conversation

benoutram
Copy link
Collaborator

@benoutram benoutram commented Mar 18, 2024

⚠️ This PR targets the .NET 8 update #4639. ⚠️
⚠️ This has associated faffy deploy task EES-5014. ⚠️

This PR updates the three function app's Data.Processor, Notifier and Publisher to run in an isolated worker process rather than use the in-process model where functions run in the same process as the Function host runtime and are dependent on the availability of .NET versions supported by the runtime.

This work followed the guide Migrate .NET apps from the in-process model to the isolated worker model which explains all the changes such as the differences in dependencies, logging, function signature, attributes, Program.cs, etc.

Switching to the isolated worker model:

  • Provides fewer version conflicts - means we aren't reliant on the host for certain built-in dependencies and we no longer need configuration to fix dependencies like EES-4463 Preserve function dependencies in build process #4227.
  • Full control of the process - means we can configure and manage services at start-up without needing an extensions project to run start-up behaviour first.
  • Standard dependency injection - With this I've changed the functions to use the Options pattern to read configuration using Options rather than reading direct from the configuration file or direct referencing Environment. This also simplifies the unit tests.
  • .NET version flexibility - The Functions 4.x runtime is currently limited to .NET 6.0 so this change is necessary to unblock our update to .NET 8.0. See Supported Versions.

See Benefits of the isolated worker model.

There's a plan for the in-process model to receive an update to support .NET 8.0 in future but the Azure Functions team have made it clear that .NET 8 will be the last LTS release to receive in-process model support.

Other changes

  • Moves all Notifier email template id's to key vault. This simplifies the infrastructure deployment, removing all the ARM template parameters for Notifier email template id's that are currently populated by Azure DevOps.
  • Moves all sensitive GovUKNotify settings (API key and email template id's) from local.settings.json into appsettings.Local.json which is already gitignored and provides new appsettings.Local.json.example file.
  • Removes unused SampleGuids class.
  • Removes unused PublicStatisticsDb connection string from Publisher's local.settings.json file.
  • Adds LocalHttpPort setting to all function projects local.settings.json files so that they don't rely on manual port configuration when running them in an IDE (or by any means other than pnpm start / start.ts which already configures the port).
  • Moves Notifier service interfaces to Notifier.Services.Interfaces namespace.

UI test result

image

@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from 3e71bbd to 465592d Compare March 19, 2024 10:09
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from 465592d to e13674b Compare March 20, 2024 10:12
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from e13674b to 285ea24 Compare March 20, 2024 10:33
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from 8734922 to 6d8438f Compare March 20, 2024 15:22
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch 2 times, most recently from 0d37a4d to 4c68d9a Compare March 20, 2024 18:55
@benoutram
Copy link
Collaborator Author

Updated UI test result after recent changes and with latest changes from #4639.

image

"ees-notify-apikey": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notify-apikey')]",
"ees-notify-apikey-admin": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notify-apikey-admin')]",
"ees-notify-token": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-notify-token')]",
"ees-admin-govuknotify-api-key": "[resourceId('Microsoft.KeyVault/vaults/secrets', variables('keyVaultName'), 'ees-admin-govuknotify-api-key')]",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I assume the faffy deploy ticket you mentioned previously is for all these changes?

I assume the plan is to add these before the deploy and then remove the old one's afterwards?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it is, I've put the details in the description of that ticket for which variables to add and remove and at what stages each thing needs doing 🙂 .

"ReleaseAmendmentSupersededSubscribersEmailTemplateId": "[parameters('releaseAmendmentSupersededSubscribersEmailTemplateId')]",
"SubscriptionConfirmationEmailTemplateId": "[parameters('subscriptionConfirmationEmailTemplateId')]",
"TableStorageConnString": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-storage-notifications')).secretUriWithVersion, ')')]"
"AppSettings:BaseUrl": "[concat(concat('https://', variables('notificationsAppName')), '.azurewebsites.net/api')]",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I like this new naming scheme - the whole Blah:Blah. What inspired this?

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok I see now - it's to do with how the configuration is accessed in C# i.e. .Configure<AppSettingOptions>(hostContext.Configuration.GetSection(AppSettingOptions.AppSettings)) in Notifier's Program.cs

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes it's to do with the Configuration API and the Options pattern. Variables in a hierarchy can be set in the environment with a double underscore or colon as the separator. We already do this for other variables in the infrastructure using the Options pattern.

"AppSettings:TableStorageConnectionString": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-storage-notifications')).secretUriWithVersion, ')')]",
"AppSettings:TokenSecretKey": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-token-secret-key'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:ApiKey": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-govuknotify-api-key'), '2018-02-14').secretUriWithVersion, ')')]",
"GovUkNotify:EmailTemplates:ReleaseAmendmentPublishedId": "[concat('@Microsoft.KeyVault(SecretUri=', reference(variables('ees-notifier-templateid-release-amendment-published'), '2018-02-14').secretUriWithVersion, ')')]",
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we add variables in the future for other projects using this naming scheme, what would we name them? Just wondering if it's worth changing these to something like GovUkNotify:EmailTemplates:Notifier:TemplateNameId?

Happy to defer to you as to what you think is best. Probably not worth the bother as you could easily see what a particular project is accessing via it's GovUkNotifyOptions class.

Copy link
Collaborator Author

@benoutram benoutram Mar 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These environment variables are defined within the Notifier function app.

If we wanted other projects to use similar names they can do without conflicting, so I don't see the need to add :Notifier: into the hierarchy.

Adding that here would mean the Options class will need a sub-class called Notifier adding into its hierarchy which would be a bit weird unless we intended to use one Options class for the entire project.

If the same Options class was applicable to multiple projects the same variable like GovUkNotify:ApiKey can be defined under multiple app's.

{
"release_link",
$"{webApplicationBaseUrl}find-statistics/{msg.PublicationSlug}/{msg.ReleaseSlug}"
$"{_appSettingOptions.PublicAppUrl}/find-statistics/{msg.PublicationSlug}/{msg.ReleaseSlug}"
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I imagine you're already aware, but AppendingTrailingSlash only appends a slash if it doesn't end with a slash already. My thought when looking at this was that maybe that's not just because the variable being set inconsistently across environments - there is some deeper reason that prevented this from being fixed in the past. I got a feeling it may be something like the frontend and backend both using the variable.

If you've already puzzled this out, feel free to ignore. Regardless, probably worth highlighting for testing.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Before I made this change I looked to see how this was configured and in all environments it was this environment variable config within the Notifier function config of the ARM template:

"WebApplicationBaseUrl": "[concat(variables('publicAppUrl'), '/')]",

The equivalent with my changes in the ARM template is now this:

"AppSettings:PublicAppUrl": "[variables('publicAppUrl')]",

With the renaming it's now clear that it's the pubic app URL and it doesn't have a trailing forward slash, so everywhere it's used has to add one but I think I've got that covered. Concatenating it before without one like this {webApplicationBaseUrl}find-statistics looked weird to me.

Comment on lines 3 to 10
"ApiKey": "",
"EmailTemplates" : {
"ReleaseAmendmentPublishedId": "",
"ReleaseAmendmentPublishedSupersededSubscribersId": "",
"ReleasePublishedId": "",
"ReleasePublishedSupersededSubscribersId": "",
"SubscriptionConfirmationId": "",
"SubscriptionVerificationId": ""
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not super fussed, but I wouldn't mind these being "change-me" (or something else) by default - that made it easy to find where you needed to change the variable, as you can grep for it.

Copy link
Collaborator Author

@benoutram benoutram Mar 21, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cool, I've changed these values back to change-me like they were before they were moved and renamed.

@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from 4c68d9a to 3a54ab4 Compare March 21, 2024 11:13
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from b15cd36 to e4cb7c8 Compare March 21, 2024 14:28
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from e4cb7c8 to 315b610 Compare March 21, 2024 16:21
@benoutram benoutram force-pushed the EES-4535-migrate-functions-to-isolated-worker-model branch from 315b610 to 2f9198b Compare March 21, 2024 16:37
@benoutram benoutram merged commit 6b77ae7 into EES-4975-dotnet8 Mar 21, 2024
2 checks passed
@benoutram benoutram deleted the EES-4535-migrate-functions-to-isolated-worker-model branch March 21, 2024 16:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants