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
Copy file name to clipboardExpand all lines: README.md
+34-7Lines changed: 34 additions & 7 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -36,9 +36,15 @@ trigger ExampleTrigger on Opportunity(after insert, after update, before delete)
36
36
37
37
That's it! Now you're ready to configure your rollups using Custom Metadata. `Rollup` makes heavy use of Entity Definition & Field Definition metadata fields, which allows you to simply select your options from within picklists, or dropdowns. This is great for giving you quick feedback on which objects/fields are available without requiring you to know the API name for every SObject and their corresponding field names.
38
38
39
+
#### Special Considerations For Use Of Custom Fields As Rollup/Lookup Fields
40
+
41
+
One **special** thing to note on the subject of Field Definitions — custom fields referenced in CMDT Field Definition fields are stored in an atypical way, and require the usage of additional SOQL queries as part of `Rollup`'s upfront cost. A typical `Rollup` operation will use `2` SOQL queries per rollup — the query that determines whether or not a job should be queued or batched, and a query for the specific Rollup Limit metadata (a dynamic query, which unfortunately means that it counts against the SOQL limits) — prior to going into the async context (where all limits are renewed) plus `1` SOQL qery (also dynamic, which is why it contributes even though it's querying CMDT). However, usage of custom fields as any of the four fields referenced in the `Rollup__mdt` custom metadata (details below) adds an additional SOQL query. If the SOQL queries used by `Rollup` becomes cause for concern, please submit an issue and we can work to address it!
42
+
43
+
#### Rollup Custom Metadata Field Breakdown
44
+
39
45
Within the `Rollup__mdt` custom metadata type, add a new record with fields:
40
46
41
-
-`Calc Item` - the SObject the calculation is derived from -- in this case, Oppportunity
47
+
-`Calc Item` - the SObject the calculation is derived from — in this case, Oppportunity
42
48
-`Lookup Object` - the SObject you’d like to roll the values up to (in this case, Account)
43
49
-`Rollup Field On Calc Item` - the field you’d like to aggregate (let's say Amount)
44
50
-`Lookup Field On Calc Item`- the field storing the Id or String referencing a unique value on another object (In the example, Id)
@@ -49,7 +55,7 @@ Within the `Rollup__mdt` custom metadata type, add a new record with fields:
49
55
-`Full Recalculation Default Number Value` (optional) - for some rollup operations (SUM / COUNT-based operations in particular), you may want to start fresh with each batch of calculation items provided. When this value is provided, it is used as the basis for rolling values up to the "parent" record (instead of whatever the pre-existing value for that field on the "parent" is, which is the default behavior). **NB**: it's valid to use this field to override the pre-existing value on the "parent" for number-based fields, _and_ that includes Date / Datetime / Time fields as well. In order to work properly for these three field types, however, the value must be converted into UTC milliseconds. You can do this easily using Anonymous Apex, or a site such as [Current Millis](https://currentmillis.com/).
50
56
-`Full Recalculation Default String Value` (optional) - same as `Full Recalculation Default Number Value`, but for String-based fields (including Lookup and Id fields).
51
57
52
-
You can perform have as many rollups as you'd like per object/trigger -- all operations are boxcarred together for optimal efficiency.
58
+
You can perform have as many rollups as you'd like per object/trigger — all operations are boxcarred together for optimal efficiency.
53
59
54
60
#### Establishing Org Limits For Rollup Operations
55
61
@@ -77,7 +83,7 @@ Invoking the `Rollup` process from a Flow, in particular, is a joy; with a Recor
77
83
78
84

79
85
80
-
This is also the preferred method for scheduling; while I do expose the option to schedule a rollup from Apex, I find the ease of use in creating Scheduled Flows in conjunction with the deep power of properly configured Invocables to be much more scalable than the "Scheduled Jobs" of old. This also gives you the chance to do some truly crazy rollups -- be it from a Scheduled Flow, an Autolaunched Flow, or a Platform Event-Triggered Flow. As long as you can manipulate data to correspond to the shape of an existing SObject's fields, they don't even have to exist; you could have an Autolaunched flow rolling up records when invoked from a REST API so long as the data you're consuming contains a String/Id matching something on the "parent" rollup object.
86
+
This is also the preferred method for scheduling; while I do expose the option to schedule a rollup from Apex, I find the ease of use in creating Scheduled Flows in conjunction with the deep power of properly configured Invocables to be much more scalable than the "Scheduled Jobs" of old. This also gives you the chance to do some truly crazy rollups — be it from a Scheduled Flow, an Autolaunched Flow, or a Platform Event-Triggered Flow. As long as you can manipulate data to correspond to the shape of an existing SObject's fields, they don't even have to exist; you could have an Autolaunched flow rolling up records when invoked from a REST API so long as the data you're consuming contains a String/Id matching something on the "parent" rollup object.
81
87
82
88
Here are the arguments necessary to invoke `Rollup` from a Flow / Process Builder:
83
89
@@ -205,6 +211,10 @@ public static Rollup sumFromTrigger(
205
211
206
212
// for using as the "one line of code" and CMDT-driven rollups
207
213
publicstaticvoid runFromTrigger()
214
+
215
+
// the alternative one-liner for CDC triggers
216
+
// more on that in the CDC section of "Special Considerations", below
217
+
publicstaticvoid runFromCDCTrigger()
208
218
```
209
219
210
220
All of the "...fromTrigger" methods shown above can also be invoked using a final argument, the `Evaluator`:
@@ -245,7 +255,7 @@ Rollup.sumFromTrigger(
245
255
246
256
It's that simple. Note that in order for custom Apex solutions that don't use the `batch` static method on `Rollup` to properly start, the `runCalc()` method must also be called. That is, if you only have one rollup operation per object, you'll _always_ need to call `runCalc()` when invoking `Rollup` from a trigger.
247
257
248
-
Another note for when the use of an `Evaluator` class might be necessary -- let's say that you have some slight lookup skew caused by a fallback object in a lookup relationship. This fallback object has thousands of objects tied to it, and updates to it are frequently painful / slow. If you didn't need the rollup for the fallback, you could implement an `Evaluator` to exclude it from being processed:
258
+
Another note for when the use of an `Evaluator` class might be necessary — let's say that you have some slight lookup skew caused by a fallback object in a lookup relationship. This fallback object has thousands of objects tied to it, and updates to it are frequently painful / slow. If you didn't need the rollup for the fallback, you could implement an `Evaluator` to exclude it from being processed:
249
259
250
260
```java
251
261
// again using the example of Opportunities
@@ -277,7 +287,7 @@ trigger OpportunityTrigger on Opportunity(before update, after update, before in
277
287
278
288
## Special Considerations
279
289
280
-
While pains have been taken to create a solution that's truly one-sized-fits-all, any professional working in the Salesforce ecosystem knows that it's difficult to make that the case for any product or service - even something open-source and forever-free, like `Rollup`. All of that is to say that while I have tested the hell out of `Rollup` and have used it already in production, your mileage may vary depending on what you're trying to do. Some operations that are explicitly not supported within the SOQL aggregate functions (like `SELECT MIN(ActivityDate) FROM Task`) are possible when using `Rollup`. Another example would be `MAX` or `MIN` operations on multi-select picklists. I don't know _why_ you would want to do that ... but you can!
290
+
While pains have been taken to create a solution that's truly one-sized-fits-all, any professional working in the Salesforce ecosystem knows that it's difficult to make that the case for any product or service — even something open-source and forever-free, like `Rollup`. All of that is to say that while I have tested the hell out of `Rollup` and have used it already in production, your mileage may vary depending on what you're trying to do. Some operations that are explicitly not supported within the SOQL aggregate functions (like `SELECT MIN(ActivityDate) FROM Task`) are possible when using `Rollup`. Another example would be `MAX` or `MIN` operations on multi-select picklists. I don't know _why_ you would want to do that ... but you can!
281
291
282
292
### Picklists
283
293
@@ -291,11 +301,11 @@ One of the reasons that `Rollup` can boast of superior performance is that, for
291
301
- a MAX operation might find that one of the calculation items supplied to it previously _was_ the _maxmimum_ value, but is no longer the max on an update
292
302
- ... pretty much any operation involving AVERAGE
293
303
294
-
In these instances, `Rollup`_does_ requery the calculation object; it also does another loop through the calculation items supplied to it in search of _all_ the values necessary to find the true rollup value. This provides context, more than anything -- the rollup operation should still be lightning fast.
304
+
In these instances, `Rollup`_does_ requery the calculation object; it also does another loop through the calculation items supplied to it in search of _all_ the values necessary to find the true rollup value. This provides context, more than anything — the rollup operation should still be lightning fast.
295
305
296
306
### Custom Apex
297
307
298
-
If you are implementing `Rollup` through the use of the static Apex methods instead of CMDT, one thing to be aware of -- if you need to perform 6+ rollup operations _and_ you are rolling up to more than one target object, you should absolutely keep your rollups ordered by the target object when invoking the `batch` method:
308
+
If you are implementing `Rollup` through the use of the static Apex methods instead of CMDT, one thing to be aware of — if you need to perform 6+ rollup operations _and_ you are rolling up to more than one target object, you should absolutely keep your rollups ordered by the target object when invoking the `batch` method:
299
309
300
310
```java
301
311
// this is perfectly valid
@@ -321,6 +331,23 @@ Rollup.batch(
321
331
);
322
332
```
323
333
334
+
### Change Data Capture (CDC)
335
+
336
+
As of [v1.0.4](https://github.com/jamessimone/apex-rollup/tree/v1.0.4), CDC _is_ supported. However, at the moment Change Data Capture can be used strictly through CMDT, and requires a different one-liner for installation into your CDC object Trigger:
337
+
338
+
```java
339
+
// within your CDC trigger, using Opportunity as an example:
340
+
trigger OpportunityChangeEventTrigger on OpportunityChangeEvent (after insert) {
341
+
Rollup.runFromCDCTrigger();
342
+
}
343
+
```
344
+
345
+
Note that you're still selecting `Opportunity` as the `Calc Item` within your Rollup metadata record in this example; in fact, you cannot select `OpportunityChangeEvent`, so hopefully that was already clear. This means that people interested in using CDC should view it as an either/or option when compared to invoking `Rollup` from a standard, synchronous trigger. Additionally, that means reparenting that occurs at the calculation item level (the child object in the rollup operation) is not yet a supported feature of `Rollup` for CDC-based rollup actions — because the underlying object has already been updated in the database, and because CDC events only contain the new values for changed fields (instead of the new & old values). It's a TBD-type situation if this will ever be supported.
346
+
347
+
### Multi-Currency Orgs
348
+
349
+
Untested. I would expect that MAX/SUM/MIN/AVERAGE operations would have undefined behavior if mixed currencies are present on the children items. This would be a good first issue for somebody looking to contribute!
350
+
324
351
## Commit History & Contributions
325
352
326
353
This repository comes after the result of [dozens of commits](https://github.com/jamessimone/apex-mocks-stress-test/commits/rollup) on my working repository. You can view the full history of the evolution of `Rollup` there.
0 commit comments