You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
>**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.
871
874
875
+
#### Internal State Tables
876
+
877
+
The trigger functionality creates several tables to use fortracking the current state of the trigger. This allows state to be persisted across sessions and for multiple instances of a trigger binding to executein parallel (for scaling purposes).
878
+
879
+
In addition, a schema named `az_func` will be created that the tables will belong to.
880
+
881
+
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.
882
+
883
+
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 functionwith a trigger binding is started, it will recreate the tables as necessary.
884
+
885
+
##### az_func.GlobalState
886
+
887
+
This table stores information about each functionbeing executed, what table that functionis 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.
888
+
889
+
##### az_func.Leases_*
890
+
891
+
A `Leases_*` table is created forevery unique instance of a function and table. The full name will bein the format `Leases_<FunctionId>_<TableId>` where `<FunctionId>` is generated from the functionID and `<TableId>` is the object ID of the table being tracked. Such as `Leases_7d12c06c6ddff24c_1845581613`.
892
+
893
+
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:
894
+
895
+
* A column foreach columnin the primary key of the target table - used to identify the row that it maps to in the target table
896
+
* A couple columns for tracking the state of each row. These are:
897
+
*`_az_func_ChangeVersion`for the change version of the row currently being processed
898
+
*`_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
899
+
* `_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.
900
+
901
+
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.
902
+
872
903
#### Trigger Samples
873
904
The trigger binding takes two [arguments](https://github.com/Azure/azure-functions-sql-extension/blob/main/src/TriggerBinding/SqlTriggerAttribute.cs)
// What should we do if this fails? It doesn't make sense to retry since it's not a connection based
335
-
// thing. We could still try to trigger on the correctly processed changes, but that adds additional
336
-
// complication because we don't want to release the leases on the incorrectly processed changes.
337
-
// For now, just give up I guess?
338
334
changes=this.ProcessChanges();
339
335
}
340
336
catch(Exceptione)
341
337
{
338
+
// Either there's a bug or we're in a bad state so not much we can do here. We'll try clearing
339
+
// our state and retry getting the changes from the top again in case something broke while
340
+
// fetching the changes.
341
+
// It doesn't make sense to retry processing the changes immediately since this isn't a connection-based issue.
342
+
// We could probably send up the changes we were able to process and just skip the ones we couldn't, but given
343
+
// that this is not a case we expect would happen during normal execution we'll err on the side of caution for
344
+
// now and just retry getting the whole set of changes.
342
345
this._logger.LogError($"Failed to compose trigger parameter value for table: '{this._userTable.FullName} due to exception: {e.GetType()}. Exception message: {e.Message}");
0 commit comments