[{"appcode":"/*\nFunction \"cron_impl_2func_651_help\" also requires \"cron_impl_2func_651\"\n\nTest Doc:\n {\n \"type\":\"recurring_event\", // The KEY will be <>::<>\n \"id\":1, //\n \"hour\":14, // The hour of the day 0-23, *, *2X, *4X to trigger\n \"min\":54, // The minute in the hour 0-59, *, *2X, *4X to trigger\n \"action\":\"doCronActionA\", // What function to run on the trigger\n \"active\":false, // Flag to arm or disable this schedule\n \"verbose\" : {\n \"user_func\":2, // Logging level for the action logic : 0=none, etc. etc.\n \"scheduler\":3 // Logging level for the cron logic : 0=none, etc. etc.\n },\n \"dynamic\" : {\n \"state\":\"arm\", // States \"arm\"|\"rearm\"|\"pending\" if any value but \"pending\" start a schedule\n \"next_sched\": 0, // Number of seconds since epoch to next desired schedule\n \"prev_sched\": 0, // Number of seconds since epoch for previous schedule\n \"prev_etime\": 0, // Number of seconds since epoch for previous schedule actual exec time\n \"prev_delay\": 0, // Number of seconds that the timer was delayed from the schedule\n \"prev_atime\": 0 // Number of seconds taken by the user 'action'\n }\n }\n \nNote, you can omit verbose{} and dynamic{} as they will be autocreated by the main Eventing \nFunction \"cron_impl_2func_651\". If verbose{} is missing the logging levels will default to \nverbose\" : { \"user_func\":1, \"scheduler\":1 }\n*/\n\nfunction tryBucketKvWriteWithLog(tag, key, doc) {\n var success = false;\n var tries = 0;\n while (tries < 10) {\n tries++;\n try {\n // critical that the below succeeds, because if it doesn't the cron cycle will break\n cron_bkt[key] = doc;\n success = true;\n break;\n } catch (e) {\n log(tag + ' ' + key + ' WARN failed to update KV tries ' + tries, e);\n }\n }\n if (!success) {\n log(tag + ' ' + +key + ' FATAL could not update KV cron cycle, tried ' + tries + ', stoping ' + curDoc.action);\n }\n return success;\n}\n\nfunction OnUpdate(doc, meta) {\n // fix for 6.5.X growing bucket ops\n if (meta.id.startsWith(\"fix_timer_scan_issue:\")) upsertOneDocPerBucket(doc, meta);\n \n try {\n // Check that doc has desired values\n if (!doc.type || doc.type !== \"recurring_event\" || !doc.active || doc.active != true) return;\n // doc must have 'action', 'dynamic {}', verbose {}, dynamic.state\n if (!doc.action || !doc.dynamic || !doc.verbose || !doc.dynamic.state) return;\n // Only process state pending this will only exist for a 'breif' time\n if (doc.dynamic.state !== \"pending\") return;\n\n var mid = doc.type + '::' + doc.id; // make our KEY\n var newdoc = null;\n try {\n // read the current version of doc from KV, e.g. curDoc\n newdoc = cron_bkt[mid];\n } catch (e) {} // needed for pre 6.5, note pure 6.5+ deployment returns null sans exception\n \n var reason = null;\n if (!newdoc || newdoc == null) {\n reason = \"cron document is missing\";\n } else\n if (!newdoc.active) {\n reason = \"cron document has active = false\";\n } else\n if (!newdoc.dynamic.state || newdoc.dynamic.state !== doc.dynamic.state) {\n reason = \"cron document wrong dynamic.state expected \" + doc.dynamic.state;\n } else\n if (crc64(doc) !== crc64(newdoc)) {\n reason = \"cron document changed\";\n }\n if (reason != null) {\n if (!newdoc || newdoc == null || newdoc.verbose.scheduler >= 1) {\n log('OnUpdate help: X stopping schedule because ' + reason + ',', newdoc)\n return;\n }\n }\n\n newdoc.dynamic.state = \"rearm\";\n // cron_bkt[mid] = newdoc;\n if (!tryBucketKvWriteWithLog('OnUpdate help: F', mid, newdoc)) {\n // Failed to write newdoc to cron_bkt[key] the error has been logged\n // and there is nothing more we can do.\n return;\n }\n\n if (newdoc.verbose.scheduler >= 1) {\n log('OnUpdate help: A ' + mid + ' mutation #2 to doc to force schedule rearm');\n }\n if (newdoc.verbose.scheduler >= 3) {\n log('OnUpdate help: B ' + mid + ',', newdoc);\n }\n } catch (e) {\n log('OnUpdate help: E ' + meta.id + ', Error exception:', e);\n }\n}\n\n// FIXUP: ADDIN FUNCTON\n// fix for 6.5.X growing bucket ops\nfunction upsertOneDocPerBucket(doc, meta) {\n\n var crcTable = makeCRC32Table();\n\n // make one doc per bucket\n var isVerbose = 0;\n var isMacOS = false; // would be nice if this was an exposed constant in Eventing\n var numvbs = 1024; // default is linux/PC\n if (isMacOS) {\n numvbs = 64;\n }\n\n var beg = (new Date).getTime();\n var result = getKeysToCoverAllPartitions(crcTable, \"_tmp_vbs:\", numvbs);\n\n for (var vb=0; vb 1 || (isVerbose == 1) && (vb < 3 || vb > numvbs -4)) {\n log(\"KEY: \" + tst);\n } else {\n if (vb == 5) console.log(\"\\t*\\n\\t*\\n\\t*\");\n }\n // update the items to trigger a mutation for our PRIMARY fucntion\n cron_bkt[tst] = { \"type\": \"_tmp_vbs\", \"vb\": vb, \"ts_millis\": beg, \"key\": tst };\n }\n var end = (new Date).getTime();\n log(\"seeding one doc to each vBucket in primary_bucket alias (took \" + (end - beg) + \" mililis)\");\n}\n\n// FIXUP: ADDIN FUNCTON\n// fix for 6.5.X growing bucket ops\nfunction showHex(n) {\n return n.toString(16);\n}\n\n// FIXUP: ADDIN FUNCTON\n// fix for 6.5.X growing bucket ops\nfunction makeCRC32Table() {\n var crcTable = [];\n var c;\n for(var n =0; n < 256; n++){\n c = n;\n for(var k =0; k < 8; k++){\n c = ((c&1) ? (0xEDB88320 ^ (c >>> 1)) : (c >>> 1));\n }\n crcTable[n] = c;\n }\n return crcTable;\n}\n\n// FIXUP: ADDIN FUNCTON\n// fix for 6.5.X growing bucket ops\nfunction crc32(crcTable,str) {\n var crc = 0 ^ (-1);\n for (var i = 0; i < str.length; i++ ) {\n crc = (crc >>> 8) ^ crcTable[(crc ^ str.charCodeAt(i)) & 0xFF];\n }\n return (crc ^ (-1)) >>> 0;\n}\n\n// FIXUP: ADDIN FUNCTON\n// fix for 6.5.X growing bucket ops\nfunction getKeysToCoverAllPartitions(crcTable,keyPrefix,partitionCount) {\n var result = [];\n var remaining = partitionCount;\n for (var i = 0; remaining > 0; i++) {\n var key = keyPrefix + i;\n var rv = (crc32(crcTable,key) >> 16) & 0x7fff;\n var actualPartition = rv & partitionCount - 1;\n if (!result[actualPartition] || result[actualPartition] === undefined) {\n result[actualPartition] = key;\n remaining--;\n }\n }\n return result;\n}","depcfg":{"buckets":[{"alias":"cron_bkt","bucket_name":"crondata","access":"rw"}],"curl":[],"metadata_bucket":"metadata","source_bucket":"crondata"},"version":"evt-6.5.1-0000-ee","handleruuid":1700638045,"id":0,"function_instance_id":"KLCDn","appname":"cron_impl_2func_651_help","settings":{"cluster_stats":null,"dcp_stream_boundary":"everything","deadline_timeout":62,"deployment_status":false,"description":"","execution_timeout":60,"language_compatibility":"6.5.0","log_level":"INFO","n1ql_consistency":"none","processing_status":false,"user_prefix":"eventing","using_timer":false,"worker_count":3},"using_timer":false,"src_mutation":true}]