You could store the topic message time in an context store object by array. You can then filter the array by a time limit, which would be your rolling window.
In this example the window is 1 minute, for testing
[{"id":"1c503a87.b15805","type":"inject","z":"30af2d3e.d94ea2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"one","payload":"test","payloadType":"str","x":140,"y":980,"wires":[["f3477ed6.6151"]]},{"id":"f3477ed6.6151","type":"function","z":"30af2d3e.d94ea2","name":"","func":"const time_window = 60000;\nlet topic_count = flow.get(\"topic_count.\" + msg.topic) || [];\nconst time_now = new Date().valueOf();\ntopic_count = topic_count.filter(time => time > (time_now-time_window));\ntopic_count.push(time_now);\nmsg.payload = topic_count.length;\nflow.set(\"topic_count.\" + msg.topic, topic_count)\nreturn msg;","outputs":1,"noerr":0,"initialize":"","finalize":"","libs":[],"x":350,"y":1000,"wires":[["2dfdae9e.4eab8a"]]},{"id":"39e839d4.2a9bc6","type":"inject","z":"30af2d3e.d94ea2","name":"","props":[{"p":"payload"},{"p":"topic","vt":"str"}],"repeat":"","crontab":"","once":false,"onceDelay":0.1,"topic":"two","payload":"another","payloadType":"str","x":150,"y":1040,"wires":[["f3477ed6.6151"]]},{"id":"2dfdae9e.4eab8a","type":"debug","z":"30af2d3e.d94ea2","name":"","active":true,"tosidebar":true,"console":false,"tostatus":false,"complete":"false","statusVal":"","statusType":"auto","x":540,"y":1160,"wires":[]}]