Skip to content

Commit 9713259

Browse files
Remove trigger binding for GA release (#732)
* Remove trigger binding for GA release * remove another test
1 parent 7e181cc commit 9713259

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

45 files changed

+7
-4479
lines changed

.vscode/settings.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,6 @@
88
"omnisharp.enableEditorConfigSupport": true,
99
"omnisharp.enableRoslynAnalyzers": true,
1010
"yaml.schemas": {
11-
"https://raw.githubusercontent.com/microsoft/azure-pipelines-vscode/master/service-schema.json": "builds/azure-pipelines/**/*.yml"
12-
},
11+
"https://raw.githubusercontent.com/microsoft/azure-pipelines-vscode/master/service-schema.json": "builds/azure-pipelines/**/*.yml"
12+
},
1313
}

README.md

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,6 @@
88
- [Supported SQL Server Versions](#supported-sql-server-versions)
99
- [Known Issues](#known-issues)
1010
- [Output Bindings](#output-bindings)
11-
- [Trigger Bindings](#trigger-bindings)
1211
- [Telemetry](#telemetry)
1312
- [Trademarks](#trademarks)
1413

@@ -18,7 +17,6 @@ This repository contains the Azure SQL bindings for Azure Functions extension co
1817

1918
- **Input Binding**: takes a SQL query or stored procedure to run and returns the output to the function.
2019
- **Output Binding**: takes a list of rows and upserts them into the user table (i.e. If a row doesn't already exist, it is added. If it does, it is updated).
21-
- **Trigger Binding**: monitors the user table for changes (i.e., row inserts, updates, and deletes) and invokes the function with updated rows.
2220

2321
For a more detailed overview of the different types of bindings see the [Bindings Overview](https://github.com/Azure/azure-functions-sql-extension/blob/main/docs/BindingsOverview.md).
2422

@@ -43,7 +41,7 @@ Databases on SQL Server, Azure SQL Database, or Azure SQL Managed Instance which
4341

4442
> **Note:** While we are actively working on resolving these issues, some may not be supported at this time. We appreciate your patience as we work to improve the Azure Functions SQL Extension.
4543
46-
- **By Design:** The table used by a SQL binding or SQL trigger cannot contain two columns that only differ by casing (Ex. 'Name' and 'name').
44+
- **By Design:** The table used by a SQL binding cannot contain two columns that only differ by casing (Ex. 'Name' and 'name').
4745
- **By Design:** Non-CSharp functions using SQL bindings against tables with columns of data types `BINARY` or `VARBINARY` need to map those columns to a string type. Input bindings will return the binary value as a base64 encoded string. Output bindings require the value upserted to binary columns to be a base64 encoded string.
4846
- **Planned for Future Support:** SQL bindings against tables with columns of data types `GEOMETRY` and `GEOGRAPHY` are not supported. Issue is tracked [here](https://github.com/Azure/azure-functions-sql-extension/issues/654).
4947
- Issues resulting from upstream dependencies can be found [here](https://github.com/Azure/azure-functions-sql-extension/issues?q=is%3Aopen+is%3Aissue+label%3Aupstream).
@@ -64,10 +62,6 @@ Databases on SQL Server, Azure SQL Database, or Azure SQL Managed Instance which
6462
- PowerShell: The workaround is to use the `$TriggerMetadata[$keyName]` to retrieve the query property - an example can be found [here](https://github.com/Azure/azure-functions-sql-extension/blob/main/samples/samples-powershell/AddProductParams/run.ps1). Issue is tracked [here](https://github.com/Azure/azure-functions-powershell-worker/issues/895).
6563
- Python: The workaround is to use `parse_qs` - an example can be found [here](https://github.com/Azure/azure-functions-sql-extension/blob/main/samples/samples-python/AddProductParams/__init__.py). Issue is tracked [here](https://github.com/Azure/azure-functions-python-worker/issues/894).
6664

67-
### Trigger Bindings
68-
69-
- **By Design:** Trigger bindings will exhibit undefined behavior if the SQL table schema gets modified while the user application is running, for example, if a column is added, renamed or deleted or if the primary key is modified or deleted. In such cases, restarting the application should help resolve any errors.
70-
7165
## Telemetry
7266

7367
This extension collect usage data in order to help us improve your experience. The data is anonymous and doesn't include any personal information. You can opt-out of telemetry by setting the `AZUREFUNCTIONS_SQLBINDINGS_TELEMETRY_OPTOUT` environment variable or the `AzureFunctionsSqlBindingsTelemetryOptOut` app setting (in your `*.settings.json` file) to '1', 'true' or 'yes';

builds/azure-pipelines/template-steps-performance.yml

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,11 +9,6 @@ parameters:
99
default:
1010
- input
1111
- output
12-
- trigger
13-
- trigger_batch
14-
- trigger_poll
15-
- trigger_overrides
16-
- trigger_parallel
1712

1813
steps:
1914
- task: UseDotNet@2

docs/BindingsOverview.md

Lines changed: 0 additions & 138 deletions
Original file line numberDiff line numberDiff line change
@@ -11,21 +11,6 @@
1111
- [Identity Columns](#identity-columns)
1212
- [Columns with Default Values](#columns-with-default-values)
1313
- [Retry support for Output Bindings](#retry-support-for-output-bindings)
14-
- [Trigger Binding](#trigger-binding)
15-
- [Change Tracking](#change-tracking)
16-
- [Functionality Overview](#functionality-overview)
17-
- [Internal State Tables](#internal-state-tables)
18-
- [az\_func.GlobalState](#az_funcglobalstate)
19-
- [az\_func.Leases\_\*](#az_funcleases_)
20-
- [Configuration for Trigger Bindings](#configuration-for-trigger-bindings)
21-
- [Sql\_Trigger\_MaxBatchSize](#sql_trigger_maxbatchsize)
22-
- [Sql\_Trigger\_PollingIntervalMs](#sql_trigger_pollingintervalms)
23-
- [Sql\_Trigger\_MaxChangesPerWorker](#sql_trigger_maxchangesperworker)
24-
- [Scaling for Trigger Bindings](#scaling-for-trigger-bindings)
25-
- [Retry support for Trigger Bindings](#retry-support-for-trigger-bindings)
26-
- [Startup retries](#startup-retries)
27-
- [Broken connection retries](#broken-connection-retries)
28-
- [Function exception retries](#function-exception-retries)
2914

3015
## Input Binding
3116

@@ -71,126 +56,3 @@ There currently is no built-in support for errors that occur while executing out
7156
If using a .NET Function then `IAsyncCollector` can be used, and the function code can handle exceptions thrown by the call to `FlushAsync()`.
7257

7358
See <https://github.com/Azure/Azure-Functions/issues/891> for further information.
74-
75-
## Trigger Binding
76-
77-
Azure SQL Trigger bindings monitor the user table for changes (i.e., row inserts, updates, and deletes) and invokes the function with updated rows.
78-
79-
### Change Tracking
80-
81-
Azure SQL Trigger bindings utilize SQL [change tracking](https://docs.microsoft.com/sql/relational-databases/track-changes/about-change-tracking-sql-server) functionality to monitor the user table for changes. As such, it is necessary to enable change tracking on the SQL database and the SQL table before using the trigger support. The change tracking can be enabled through the following two queries.
82-
83-
1. Enabling change tracking on the SQL database:
84-
85-
```sql
86-
ALTER DATABASE ['your database name']
87-
SET CHANGE_TRACKING = ON
88-
(CHANGE_RETENTION = 2 DAYS, AUTO_CLEANUP = ON);
89-
```
90-
91-
The `CHANGE_RETENTION` option specifies the duration for which the changes are retained in the change tracking table. This may affect the trigger functionality. For example, if the user application is turned off for several days and then resumed, it will only be able to catch the changes that occurred in past two days with the above query. Hence, please update the value of `CHANGE_RETENTION` to suit your requirements. The `AUTO_CLEANUP` option is used to enable or disable the clean-up task that removes the stale data. Please refer to SQL Server documentation [here](https://docs.microsoft.com/sql/relational-databases/track-changes/enable-and-disable-change-tracking-sql-server#enable-change-tracking-for-a-database) for more information.
92-
93-
1. Enabling change tracking on the SQL table:
94-
95-
```sql
96-
ALTER TABLE dbo.Employees
97-
ENABLE CHANGE_TRACKING;
98-
```
99-
100-
For more information, please refer to the documentation [here](https://docs.microsoft.com/sql/relational-databases/track-changes/enable-and-disable-change-tracking-sql-server#enable-change-tracking-for-a-table). The trigger needs to have read access on the table being monitored for changes as well as to the change tracking system tables. It also needs write access to an `az_func` schema within the database, where it will create additional leases tables to store the trigger states and leases. Each function trigger will thus have an associated change tracking table and leases table.
101-
102-
> **NOTE:** The leases table contains all columns corresponding to the primary key from the user table and three additional columns named `_az_func_ChangeVersion`, `_az_func_AttemptCount` and `_az_func_LeaseExpirationTime`. If any of the primary key columns happen to have the same name, that will result in an error message listing any conflicts. In this case, the listed primary key columns must be renamed for the trigger to work.
103-
104-
### Functionality Overview
105-
106-
The Azure SQL Trigger binding uses a polling loop to check for changes, triggering the user function when changes are detected. At a high level the loop looks like this :
107-
108-
```
109-
while (true) {
110-
1. Get list of changes on table - up to a maximum number controlled by the Sql_Trigger_MaxBatchSize setting
111-
2. Trigger function with list of changes
112-
3. Wait for delay controlled by Sql_Trigger_PollingIntervalMs setting
113-
}
114-
```
115-
116-
Changes will always be processed in the order that their changes were made, with the oldest changes being processed first. A couple notes about this :
117-
118-
1. If changes to multiple rows are made at once the exact order that they'll be sent to the function is based on the order returned by the CHANGETABLE function
119-
2. Changes are "batched" together for a row - if multiple changes are made to a row between each iteration of the loop than only a single change entry will exist for that row that shows the difference between the last processed state and the current state
120-
3. If changes are made to a set of rows, and then another set of changes are made to half of those same rows then the half that wasn't changed a second time will be processed first. This is due to the above note with the changes being batched - the trigger will only see the "last" change made and use that for the order it processes them in
121-
122-
See [Work with change tracking](https://learn.microsoft.com/sql/relational-databases/track-changes/work-with-change-tracking-sql-server) for more information on change tracking and how it is used by applications such as Azure SQL triggers.
123-
124-
### Internal State Tables
125-
126-
The trigger functionality creates several tables to use for tracking the current state of the trigger. This allows state to be persisted across sessions and for multiple instances of a trigger binding to execute in parallel (for scaling purposes).
127-
128-
In addition, a schema named `az_func` will be created that the tables will belong to.
129-
130-
The login the trigger is configured to use must be given permissions to create these tables and schema. If not, then an error will be thrown and the trigger will fail to run.
131-
132-
If the tables are deleted or modified, then unexpected behavior may occur. To reset the state of the triggers, first stop all currently running functions with trigger bindings and then either truncate or delete the tables. The next time a function with a trigger binding is started, it will recreate the tables as necessary.
133-
134-
#### az_func.GlobalState
135-
136-
This table stores information about each function being executed, what table that function is watching and what the [last sync state](https://learn.microsoft.com/sql/relational-databases/track-changes/work-with-change-tracking-sql-server) that has been processed.
137-
138-
#### az_func.Leases_*
139-
140-
A `Leases_*` table is created for every unique instance of a function and table. The full name will be in the format `Leases_<FunctionId>_<TableId>` where `<FunctionId>` is generated from the function ID and `<TableId>` is the object ID of the table being tracked. Such as `Leases_7d12c06c6ddff24c_1845581613`.
141-
142-
NOTE: `FunctionId` is generated from a couple of inputs:
143-
- The HostId, which is a hash of the assembly name containing the function
144-
- The full class and method name of the function
145-
146-
If either of these values are changed then a new FunctionId will be generated and result in the function starting over from the beginning, including creating a new Leases table.
147-
148-
This table is used to ensure that all changes are processed and that no change is processed more than once. This table consists of two groups of columns:
149-
150-
- A column for each column in the primary key of the target table - used to identify the row that it maps to in the target table
151-
- A couple columns for tracking the state of each row. These are:
152-
- `_az_func_ChangeVersion` for the change version of the row currently being processed
153-
- `_az_func_AttemptCount` for tracking the number of times that a change has attempted to be processed to avoid getting stuck trying to process a change it's unable to handle
154-
- `_az_func_LeaseExpirationTime` for tracking when the lease on this row for a particular instance is set to expire. This ensures that if an instance exits unexpectedly another instance will be able to pick up and process any changes it had leases for after the expiration time has passed.
155-
156-
A row is created for every row in the target table that is modified. These are then cleaned up after the changes are processed for a set of changes corresponding to a change tracking sync version.
157-
158-
### Configuration for Trigger Bindings
159-
160-
This section goes over some of the configuration values you can use to customize SQL trigger bindings. See [How to Use Azure Function App Settings](https://learn.microsoft.com/azure/azure-functions/functions-how-to-use-azure-function-app-settings) to learn more.
161-
162-
#### Sql_Trigger_MaxBatchSize
163-
164-
This controls the maximum number of changes sent to the function during each iteration of the change processing loop.
165-
166-
#### Sql_Trigger_PollingIntervalMs
167-
168-
This controls the delay in milliseconds between processing each batch of changes.
169-
170-
#### Sql_Trigger_MaxChangesPerWorker
171-
172-
This controls the upper limit on the number of pending changes in the user table that are allowed per application-worker. If the count of changes exceeds this limit, it may result in a scale out. The setting only applies for Azure Function Apps with runtime driven scaling enabled. See the [Scaling](#scaling-for-trigger-bindings) section for more information.
173-
174-
### Scaling for Trigger Bindings
175-
176-
If your application containing functions with SQL trigger bindings is running as an Azure function app, it will be scaled automatically based on the amount of changes that are pending to be processed in the user table. As of today, we only support scaling of function apps running in Elastic Premium plan. To enable scaling, you will need to go the function app resource's page on Azure Portal, then to Configuration > 'Function runtime settings' and turn on 'Runtime Scale Monitoring'. For more information, check documentation on [Runtime Scaling](https://learn.microsoft.com/azure/azure-functions/event-driven-scaling#runtime-scaling). You can configure scaling parameters by going to 'Scale out (App Service plan)' setting on the function app's page. To understand various scale settings, please check the respective sections in [Azure Functions Premium plan](https://learn.microsoft.com/azure/azure-functions/functions-premium-plan?tabs=portal#eliminate-cold-starts)'s documentation.
177-
178-
There are a couple of checks made to decide on whether the host application needs to be scaled in or out. The rationale behind these checks is to ensure that the count of pending changes per application-worker stays below a certain maximum limit, which is defaulted to 1000, while also ensuring that the number of workers running stays minimal. The scaling decision is made based on the latest count of the pending changes and whether the last 5 times we checked the count, we found it to be continuously increasing or decreasing.
179-
180-
### Retry support for Trigger Bindings
181-
182-
#### Startup retries
183-
184-
If an exception occurs during startup then the host runtime will automatically attempt to restart the trigger listener with an exponential backoff strategy. These retries will continue until either the listener is successfully started or the startup is cancelled.
185-
186-
#### Broken connection retries
187-
188-
If the function successfully starts but then an error causes the connection to break (such as the server going offline) then the function will continue to try and reopen the connection until the function is either stopped or the connection succeeds. If the connection is successfully re-established then it will pick up processing changes where it left off.
189-
190-
Note that these retries are outside the built in idle connection retry logic that SqlClient has which can be configured with the [ConnectRetryCount](https://learn.microsoft.com/dotnet/api/system.data.sqlclient.sqlconnectionstringbuilder.connectretrycount) and [ConnectRetryInterval](https://learn.microsoft.com/dotnet/api/system.data.sqlclient.sqlconnectionstringbuilder.connectretryinterval) connection string options. The built-in idle connection retries will be attempted first and if those fail to reconnect then the trigger binding will attempt to re-establish the connection itself.
191-
192-
#### Function exception retries
193-
194-
If an exception occurs in the user function when processing changes then those rows will be retried again in 60 seconds. Other changes will be processed as normal during this time, but the rows that caused the exception will be ignored until the timeout period has elapsed.
195-
196-
If the function execution fails 5 times in a row for a given row then that row is completely ignored for all future changes.

docs/GeneralSetup.md

Lines changed: 0 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -87,37 +87,6 @@ GRANT SELECT, INSERT, UPDATE ON <TableName> TO <UserName>
8787

8888
**NOTE**: In some scenarios, the presence of table components such as a SQL DML trigger may require additional permissions for the output binding to successfully complete the operation.
8989

90-
### Trigger Permissions
91-
92-
- `CREATE SCHEMA` and `CREATE TABLE` permissions on database
93-
94-
This is required to create the [Internal State Tables](./BindingsOverview.md#internal-state-tables) required by the trigger.
95-
96-
```sql
97-
USE <DatabaseName>
98-
GRANT CREATE SCHEMA TO <UserName>
99-
GRANT CREATE TABLE TO <UserName>
100-
```
101-
102-
- `SELECT` and `VIEW CHANGE TRACKING` permissions on the table
103-
104-
These are required to retrieve the data about the changes occurring in the table.
105-
106-
```sql
107-
USE <DatabaseName>
108-
GRANT SELECT ON <TableName> TO <UserName>
109-
```
110-
111-
- `SELECT`, `INSERT`, `UPDATE` and `DELETE` permissions on `az_func` schema
112-
- Note this is usually automatically inherited if the login being used was the one that created the schema in the first place. If another user created the schema or ownership was changed afterwards then these permissions will need to be reapplied for the function to work.
113-
114-
These are required to read and update the internal state of the function.
115-
116-
```sql
117-
USE <DatabaseName>
118-
GRANT SELECT, INSERT, UPDATE, DELETE ON SCHEMA::az_func TO <UserName>
119-
```
120-
12190
## Create a Function Project
12291

12392
Now you will need a Function Project to add the binding to. If you have one created already you can skip this step.

0 commit comments

Comments
 (0)