I have been struggling for a very long time to achieve deleting old data in the realtime database using cloud functions. What am I doing wrong?
I want to delete data that's older than 2 hours every 60 minutes.
const functions = require('firebase-functions');
const admin = require('firebase-admin');
admin.initializeApp();
'use strict';
const CUT_OFF_TIME = 2 * 60 * 60 * 1000; // 2 Hours in milliseconds.
exports.deleteOldItems = functions.pubsub.schedule('every 60 minutes').onRun(async context => {
admin.database().ref('/').once('value', async (data) => {
var ref = data.val();
const now = Date.now();
const cutoff = now - CUT_OFF_TIME;
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
const snapshot = await oldItemsQuery.once('value');
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
});
});
I didn't check your code for the query based on the cutoff, but we can already see that
var ref = data.val();
//...
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
//...
return ref.update(updates);
cannot work because data.val() is not a Reference.
You should adapt your code as follows (untested):
exports.deleteOldItems = functions.pubsub.schedule('every 60 minutes').onRun(async (context) => {
const ref = admin.database().ref();
const now = Date.now();
const cutoff = now - CUT_OFF_TIME;
const oldItemsQuery = ref.orderByChild('timestamp').endAt(cutoff);
const snapshot = await oldItemsQuery.get();
// create a map with all children that need to be removed
const updates = {};
snapshot.forEach(child => {
updates[child.key] = null;
});
return ref.update(updates);
});
Related
I have app witch visualize sorting alogrith i want to show user how much memory used each one of them when was runned it should be done on button click my stack is typescript and d3.js . I use Vite.js for building the app.
This is the button click code so far
let sortingInProgress = false
let timeInfo = '0.00 s'
const sortingPromise = new Promise<void>(resolve => {
START_BUTTON.addEventListener('click', async () => {
if (sortingInProgress) {
console.log('stoped')
return
}
sortingInProgress = true
START_BUTTON.disabled = true
SELECT_DATA_SIZE.disabled = true
SELECT_SORTING_ALGORITHM.disabled = true
const startTime = performance.now()
const sort = SelectAlgorithm(data, algorithmType)
await sort(updateBars)
const endTime = performance.now()
const totalTime = ((endTime - startTime) / 1000).toFixed(2) // get alogrithm running time in seconds
console.log(totalTime)
timeInfo = `${totalTime} s`
resolve()
})
})
sortingPromise.then(() => {
svg.selectAll('rect').style('fill', 'black')
sortingInProgress = false
SELECT_DATA_SIZE.disabled = false
SELECT_SORTING_ALGORITHM.disabled = false
SORT_TIME.textContent = timeInfo
})
I working on this streamer leaderboard project that only allows vanilla React. However, you need to move the streamer up or down in real-time whenever their points go up or down in rank. Since this is frontend test, I only used a Math.random() to change the streamer's points state. The animation would be like this link below(of course without clicking). I was thinking CSS animations, but not really sure how I can connect an animation to a useState update. Below, is a bit of my code as a reference.
Animation Example
const [streamerList, setStreamersList] = useState<StreamerType[]>([]);
useEffect(() => {
const getData = async () => {
const res = await fetch(
'https://webcdn.17app.co/campaign/pretest/data.json'
);
const data = await res.json();
const item = data;
setStreamersList(item);
//error catch handle
};
getData();
}, []);
//for now lets just add the fetching and later move it into a new folder
useEffect(() => {
const randomizer = () => {
let newArr = [...streamerList];
const eleSelect = Math.floor(Math.random() * (streamerList.length - 1));
const status = Math.floor(Math.random() * 2);
switch (status) {
case 0:
newArr[eleSelect].score =
newArr[eleSelect].score + Math.floor(Math.random() * 500);
newArr = newArr.sort((a, b) => b.score - a.score);
setStreamersList(newArr);
break;
case 1:
newArr[eleSelect].score =
newArr[eleSelect].score - Math.floor(Math.random() * 500);
newArr = newArr.sort((a, b) => b.score - a.score);
setStreamersList(newArr);
break;
default:
console.log('test');
}
};
//need a randomizer which element in the array
const interval = setInterval(() => {
randomizer();
//add all the other randomize && we do the set add /sub the points here
//TODO: there is a gap between adding, it seems like it should be none should nonexistent
}, 100);
return () => clearInterval(interval);
}, [streamerList.length, streamerList]);
return (
// TODO: unique key prop is have issues here for some reason
<LeaderBoard>
{streamerList.map((ele, index) => (
<Streamer
number={index}
userId={ele.userID}
displayName={ele.displayName}
picture={ele.picture}
score={ele.score}
/>
))}
</LeaderBoard>
);
I'd like to be able to track how loud the song gets in realtime, returning a number to represent the current volume of the song. The source is from a sample that plays when you click it. Ive seen tutorials on making a volume meter, but all I want is a number to measure this. here is my starting code.
const audioContext = new AudioContext();
const samplebutton = document.createElement('button')
samplebutton.innerText = 'sample'
samplebutton.addEventListener('click', async () => {
let volume = 0
const response = await fetch('testsong.wav')
const soundBuffer = await response.arrayBuffer()
const sampleBuffer = await audioContext.decodeAudioData(soundBuffer)
const sampleSource = audioContext.createBufferSource()
sampleSource.buffer = sampleBuffer
sampleSource.connect(audioContext.destination)
sampleSource.start()
function TrackVolume(){
}
You can calculate the volume by passing the audio through an AnalyserNode. With it you can get the amplitudes of every frequency at a specific moment in time and calculate the volume of the audio file.
const audioContext = new AudioContext();
const samplebutton = document.createElement('button')
samplebutton.innerText = 'sample'
samplebutton.addEventListener('click', async () => {
const response = await fetch('testsong.wav')
const soundBuffer = await response.arrayBuffer()
const sampleBuffer = await audioContext.decodeAudioData(soundBuffer)
const analyser = audioContext.createAnalyser();
const sampleSource = audioContext.createBufferSource()
sampleSource.buffer = sampleBuffer
const bufferLength = analyser.frequencyBinCount;
const dataArray = new Uint8Array(bufferLength);
sampleSource.connect(analyser);
analyser.connect(audioContext.destination)
sampleSource.start()
function caclculateVolume() {
analyser.getByteFrequencyData(dataArray)
let sum = 0;
for (const amplitude of dataArray) {
sum += amplitude * amplitude
}
const volume = Math.sqrt(sum / dataArray.length)
console.log(volume)
requestAnimationFrame(caclculateVolume)
}
caclculateVolume()
});
I am working on a performance issue of a function, that takes 15sec to response, which makes a request to firebase for all documents that are
"ErrorID" "==" "0"
The problem is that there are many documents and they are kind of very large objects, and I only need TWO FIELDS (Order and Amount) of each document, there are any way to request only those two fields that accomplish the condition?
Something like :
firestore.collection("purchases").where("ErrorID", "==", "0").get(Order, Amount);
The function that im talking about:
const totalEarn = async (req, res, next) => {
const DAY = 86400000;
const WEEK = 604800016;
const MONTH = 2629800000;
try {
let snap = await firestore.collection("purchases").where("ErrorID", "==", "0").get(); // CONDITION
let totalToday = 0;
let totalYesterday = 0;
let totalLastWeek = 0;
let totalLastMonth = 0;
let now = Date.now();
let Yesterday = now - 86400000;
await snap.forEach((doc) => { // THIS FOR EACH TAKES TOO MUCH TIME
let info = doc.data();
let time = info.Order.split("-")[2]; // FIRESTORE FIELD -> ORDER
let amount = info.AmountEur * 1; // FIRESTORE FIELD -> AMOUNT
if (time > now - DAY) {
totalToday = totalToday + amount;
}
if (time < now - DAY && time > Yesterday - DAY) {
totalYesterday = totalYesterday + amount;
}
if (time > now - WEEK) {
totalLastWeek = totalLastWeek + amount;
}
if (time > now - MONTH) {
totalLastMonth = totalLastMonth + amount;
}
});
res.send({
status: true,
data: {
totalToday: totalToday.toFixed(2),
totalYesterday: totalYesterday.toFixed(2),
totalLastWeek: totalLastWeek.toFixed(2),
totalLastMonth: totalLastMonth.toFixed(2),
},
});
} catch (error) {
res.status(410).send({
status: false,
error: "some error occured counting the numbers",
e: error.message,
});
}
};
The document im talking about
If you use Firestore Node.JS client or Firebase Admin SDK, then you can use select() to select fields:
import { Firestore } from "#google-cloud/firestore";
const firestore = new Firestore();
const snap = firestore
.collection("purchases")
.where("ErrorID", "==", "0")
.select("Order", "Amount")
.get();
Bear with me, I just started learning JS yesterday trying to make a HTML clock by putting multiple tutorials' results together.
I made two looping animations using 2 arrays, with the intent of switching between arrays depending on if it's earlier or later than 8pm. I would like for my code to constantly check if it's 8pm every X amount of seconds, and only re-run the script if the IF result or output is different than what it currently is.
const now = new Date();
if (now.getHours() > 20) { // Time checker!!!!!
var hat = ['A','B','C','D'],
a = -1;
(function f(){
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
setTimeout(f, 1000);
})();
} else {
var hat = ['1','2','3','4'],
a = -1;
(function f(){
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
setTimeout(f, 1000);
})();
}
I have tried setInterval however it re-runs the script even if the IF result has not changed, and messes up the animation.
I.E - if it's 6pm, it tries to play the animation from the start every 1 second and the frames get messed up.
Any advice or help would be great, thanks!
I tried to save your code.
const checkTimeDelay = 1000;
let isAbove8PM = null;
let curTimeHandler = null;
let intervalId = null;
// checking if is above 8 pm
const checkTime = () => {
const now = new Date();
if (now.getHours() > 20) {
return true;
}
return false;
};
const above8PMHandler = () => {
var hat = ['A','B','C','D'],
a = -1;
return () => {
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
// setTimeout(f, 1000);
};
};
const before8PMHandler = () => {
var hat = ['1','2','3','4'],
a = -1;
return () => {
a = (a + 1) % hat.length;
const hatformatted = `${(hat[ a ])}`;
document.querySelector(".main").textContent = hatformatted;
// setTimeout(f, 1000);
};
};
// restart clock interval on based on new handler (above8PMHandler|before8PMHandler)
const rebaseClockInterval = () => {
clearInterval(intervalId);
intervalId = setInterval(curTimeHandler, 1000);
};
// main func, checks if we should change clocks handler (above8PMHandler|before8PMHandler)
const clockTick = () => {
const curTimeChecked = checkTime();
if (curTimeChecked === isAbove8PM) { return; }
isAbove8PM = curTimeChecked;
if (isAbove8PM) {
curTimeHandler = above8PMHandler();
} else {
curTimeHandler = before8PMHandler();
}
curTimeHandler();
rebaseClockInterval();
};
// start main func
setInterval(clockTick, checkTimeDelay);
I also provide some ideas here.
function setClockInterval() {
const hat1 = ['A', 'B', 'C', 'D'];
const hat2 = ['1', '2', '3', '4'];
let prevCheck = null;
let count = 0;
const checker = () => {
return new Date().getSeconds() > 20;
};
const next = () => {
count++;
};
const reset = () => {
count = 0;
};
const render = (content) => {
// console.log(`clockInterval ${content}`); // debug output
document.querySelector(".main").textContent = content;
};
const fn = () => {
const check = checker();
const arr = check ? hat1 : hat2;
// empty arr skip
if (arr.length <= 0)
return;
// restart count to 0
if (prevCheck !== null && prevCheck !== check)
reset();
render(arr[count % arr.length]);
prevCheck = check;
next();
};
return setInterval(fn, 1000);
}
// start interval
const clock = setClockInterval();
// stop
clearInterval(clock);
You can greatly simplify your code by removing everything from inside the if block that is repeated and running it afterward. You also need to get a new Date on each iteration, otherwise the array won't change when it gets to the designated time.
I have changed the condition check to be odd/even seconds to show how it swaps between arrays without losing the index.
// Global, could be kept inside closure
let a = -1;
// Function to run each iteration
(function f() {
// OP code
// let hat = new Date().getHours() > 18? ['A','B','C','D'] : ['1','2','3','4'];
// faster iteration as example
let hat = new Date().getSeconds() % 2? ['A','B','C','D'] :['1','2','3','4'];
a = (a + 1) % hat.length;
document.querySelector(".main").textContent = hat[a];
setTimeout(f, 1000);
})();
<div class="main"></div>