I realize that it's currently unstable, but does anyone have an example of using exclusive file locking with Deno? Or for that matter, how to get/use the resource id for a specific file path.
Deno.flock
Here's the test that was included in the PR that implemented the feature. It answers both of your questions:
Note that it has evolved since the PR.
flock_test.ts:
// Copyright 2018-2021 the Deno authors. All rights reserved. MIT license.
import { assertEquals, unitTest } from "./test_util.ts";
unitTest(
{ perms: { read: true, run: true, hrtime: true } },
async function flockFileSync() {
const path = "cli/tests/testdata/fixture.json";
const script = (exclusive: boolean, wait: number) => `
const { rid } = Deno.openSync("${path}");
Deno.flockSync(rid, ${exclusive ? "true" : "false"});
await new Promise(res => setTimeout(res, ${wait}));
Deno.funlockSync(rid);
`;
const run = (e: boolean, w: number) =>
Deno.run({ cmd: [Deno.execPath(), "eval", "--unstable", script(e, w)] });
const firstBlocksSecond = async (
first: boolean,
second: boolean,
): Promise<boolean> => {
const firstPs = run(first, 1000);
await new Promise((res) => setTimeout(res, 250));
const start = performance.now();
const secondPs = run(second, 0);
await secondPs.status();
const didBlock = (performance.now() - start) > 500;
firstPs.close();
secondPs.close();
return didBlock;
};
assertEquals(
await firstBlocksSecond(true, false),
true,
"exclusive blocks shared",
);
assertEquals(
await firstBlocksSecond(false, true),
true,
"shared blocks exclusive",
);
assertEquals(
await firstBlocksSecond(true, true),
true,
"exclusive blocks exclusive",
);
assertEquals(
await firstBlocksSecond(false, false),
false,
"shared does not block shared",
);
},
);
unitTest(
{ perms: { read: true, run: true, hrtime: true } },
async function flockFileAsync() {
const path = "cli/tests/testdata/fixture.json";
const script = (exclusive: boolean, wait: number) => `
const { rid } = await Deno.open("${path}");
await Deno.flock(rid, ${exclusive ? "true" : "false"});
await new Promise(res => setTimeout(res, ${wait}));
await Deno.funlock(rid);
`;
const run = (e: boolean, w: number) =>
Deno.run({ cmd: [Deno.execPath(), "eval", "--unstable", script(e, w)] });
const firstBlocksSecond = async (
first: boolean,
second: boolean,
): Promise<boolean> => {
const firstPs = run(first, 1000);
await new Promise((res) => setTimeout(res, 250));
const start = performance.now();
const secondPs = run(second, 0);
await secondPs.status();
const didBlock = (performance.now() - start) > 500;
firstPs.close();
secondPs.close();
return didBlock;
};
assertEquals(
await firstBlocksSecond(true, false),
true,
"exclusive blocks shared",
);
assertEquals(
await firstBlocksSecond(false, true),
true,
"shared blocks exclusive",
);
assertEquals(
await firstBlocksSecond(true, true),
true,
"exclusive blocks exclusive",
);
assertEquals(
await firstBlocksSecond(false, false),
false,
"shared does not block shared",
);
},
);
Related
When I run my react-project on my local machine, useQuery doesn't fetch data multiple-time, it renders data only on first-time loading.
const [todayAttendance, setTodayAttendance] = React.useState([]);
const {
data: allAttendance,
isLoading: attendanceIsLoading,
isError: attendanceIsError,
} = useQuery(
["todaysAbsent", branchId],
async () =>
myAxios(`/all_attendance/${moment().format("MM")}/${moment().format(
"YYYY"
)}/?branch_id=${branchId ?? ""}`
),
{
onSuccess: (e) => {
setTodayAttendance([]);
Object.values(e.data).filter(
({ attendance, name, position, information_user }, i) =>
setTodayAttendance((prev) => [
...prev,
{
attendance: attendance[`${moment().format("YYYY-MM-DD")}`],
id: i,
status:
attendance[`${moment().format("YYYY-MM-DD")}`]["status"],
name: name,
position: position,
information_user: information_user,
},
])
);
},
}
I'm trying to pass the queryKey variable alongside the pageParam in useInfiniteQuery? I've tried for a while but:
Cannot get the page data
In some cases, the data is rendered repeatedly.
How should I pass the variables?
export const fetchInfiniteVariants = async (
filters = {},
{ pageParam = 0 }
) => {
const records = await axios.get(baseURL, {
headers: authHeader,
params: {
pageSize: 24,
offset: pageParam,
fields: [
"name",
"packshot",
"packshot_size",
"brand_logo",
"price",
"slug",
],
// filterByFormula: `({validated} = 1)`,
filterByFormula: `(${filterByFields(filters)})`,
"sort[0][field]": "priority",
"sort[0][direction]": "asc",
},
})
return records
}
export const useInfiniteVariantsQuery = (
initialRecords,
offset,
filters = { brand: "HAY" }
) => {
const infiniteVariantsQuery = useInfiniteQuery(
["infiniteVariants", filters],
() => fetchInfiniteVariants(filters),
{
initialStale: true,
staleTime: 6000,
getNextPageParam: (lastPage, pages) => lastPage.data.offset,
}
)
return {
...infiniteVariantsQuery,
}
}
The queryFn you're passing to useInfiniteQuery has request context as a parameter to that callback, as documented on the useInfiniteQuery page:
Receives a QueryFunctionContext object with the following variables:
queryKey: EnsuredQueryKey: the queryKey, guaranteed to be an Array
pageParam: unknown | undefined
You can destructure and retrieve your queryKey from that, as below:
export const useInfiniteVariantsQuery = (
initialRecords,
offset,
filters = { brand: "HAY" }
) => {
const infiniteVariantsQuery = useInfiniteQuery(
["infiniteVariants", filters],
({ queryKey, pageParam }) => fetchInfiniteVariants(queryKey[1], pageParam),
{
initialStale: true,
staleTime: 6000,
getNextPageParam: (lastPage, pages) => lastPage.data.offset,
}
)
return {
...infiniteVariantsQuery,
}
}
TICKET PROBLEM
When I reopen the ticket and want to close it again, the "interaction.channel.edit" function is not working, why?
There are no errors, version v13
When I close my ticket before reopening, everything is fine
//Now I am writing a sample message because they are stating that I wrote the code alone
const client = require("../index");
const { createTranscript } = require('discord-html-transcripts');
const { MessageEmbed, MessageActionRow, MessageButton, Message } = require("discord.js");
client.on("interactionCreate", async (interaction) => {
// Slashe
if (interaction.isCommand()) {
await interaction.deferReply({ ephemeral: false }).catch((error) => { console.log(error)});
const cmd = client.slashCommands.get(interaction.commandName);
if (!cmd)
return interaction.followUp({ content: "Wystapil jakis blad!" });
const args = [];
for (let option of interaction.options.data) {
if (option.type === "SUB_COMMAND") {
if (option.name) args.push(option.name);
option.options?.forEach((x) => {
if (x.value) args.push(x.value);
});
} else if (option.value) args.push(option.value);
}
interaction.member = interaction.guild.members.cache.get(interaction.user.id);
cmd.run(client, interaction, args);
}
// Context menu
if (interaction.isContextMenu()) {
await interaction.deferReply({ ephemeral: false });
const command = client.slashCommands.get(interaction.commandName);
if (command) command.run(client, interaction);
}
// Buttony
if(interaction.isButton()) {
await interaction.deferUpdate()
if(interaction.customId === 'verify') {
let error = 0
const roleAdd = interaction.guild.roles.cache.get('949702807517265930')
const roleRemove = interaction.guild.roles.cache.get('949702776508792864')
if(!interaction.guild.me.permissions.has('ADMINISTRATOR')) {
const channel = interaction.guild.channels.cache.get("949716268146131066")
const embed = new MessageEmbed()
.setColor('RED')
.setTitle("ERROR")
.setDescription("Nie posiadam permissji potrzebnych do weryfikacji!")
.setTimestamp();
error = 1
channel.send({ embeds:[embed]});
}
if(interaction.guild.me.roles.highest.position <= roleAdd.position){
const channel = interaction.guild.channels.cache.get("949716268146131066")
const embed = new MessageEmbed()
.setColor('RED')
.setTitle("ERROR")
.setDescription("Moja rola jest niżej niż rola, którą dodaje podczas weryfikacji!")
.setTimestamp();
error = 1
channel.send({ embeds:[embed]});
}
if(interaction.guild.me.roles.highest.position <= roleRemove.position){
const channel = interaction.guild.channels.cache.get("949716268146131066")
const embed = new MessageEmbed()
.setColor('RED')
.setTitle("ERROR")
.setDescription("Moja rola jest niżej niż rola, którą zabieram podczas weryfikacji")
.setTimestamp();
error = 1
channel.send({ embeds:[embed]});
}
if(error > 0){
interaction.guild.members.cache.get("613438379174133770").send("Błąd podczas weryfikacji!")
return interaction.member.send("Wystąpił błąd podczas weryfikacji!");
}
await interaction.member.roles.add(roleAdd)
await interaction.member.roles.remove(roleRemove)
interaction.member.send("Pomyślnie zweryfikowano!")
}if(interaction.customId === 'ticket-open'){
if(interaction.guild.channels.cache.find(ch => ch.topic == interaction.user.id)) {
return interaction.followUp({
content: `Posiadasz już ticket!`,
ephemeral: true
})}
interaction.guild.channels.create(`Ticket-${interaction.user.username}`, {
parent: '949978511324635136',
permissionOverwrites: [{
id: interaction.user.id,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES']
},
{
id: '949701839560011797',
deny: ['VIEW_CHANNEL', 'SEND_MESSAGES']
},
{
id: client.user.id,
allow: ['VIEW_CHANNEL', 'SEND_MESSAGES']
}],
topic: interaction.user.id
})
.then(async(tick) => {
interaction.followUp({
content: `Ticket otworzony <#${tick.id}>`,
ephemeral: true
})
const tickEmbed = new MessageEmbed()
.setColor('GREEN')
.setFooter({
text: `${interaction.user.username} ${new Date().getFullYear()}`,
iconURL: interaction.user.displayAvatarURL({ dynamic: true })
})
.setTitle("Ticket")
.setDescription(`**Otworzyłeś/aś ticket, poczekaj cierpliwie, aż ktoś z administracji Cie obsłuży, nie pinguj oraz zachowaj kulturę na tickecie**`);
const closeButton = new MessageButton()
.setCustomId("close-button")
.setLabel("Zamknij")
.setEmoji("🔒")
.setStyle("SECONDARY");
const row = new MessageActionRow()
.setComponents(closeButton);
tick.send({
content: `Cześć <#${interaction.user.id}>, administracja za chwilę Cie obsłuży <#&949982338031423541>`,
embeds: [tickEmbed],
components: [row]
})
})
} if(interaction.customId === 'close-button'){
if(interaction.channel.name.includes(`zamkniety`)) return interaction.followUp({ content: 'Ticket jest już zamknięty!', ephemeral: true });
const buttonTak = new MessageButton()
.setCustomId('close-tak')
.setLabel('Zamknij')
.setStyle('SECONDARY')
const buttonNie = new MessageButton()
.setCustomId('close-nie')
.setLabel('Anuluj')
.setStyle('DANGER')
const raw = new MessageActionRow()
.setComponents([buttonTak, buttonNie])
interaction.channel.send({
content:'Czy napewno chcesz zamknąć ticket?',
components: [raw]
})
} if(interaction.customId === 'close-tak'){
const usd = interaction.guild.members.cache.get(interaction.channel.topic)
const name = usd.user.username
interaction.channel.edit({
name: "zamkniety",
permissionOverwrites: [{
id: interaction.channel.topic,
deny: ['SEND_MESSAGES', 'VIEW_CHANNEL']
}, {
id: '949701839560011797',
deny: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
}, {
id: client.user.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
}],
})
const message = await interaction.channel.messages.fetch(interaction.message.id).catch(() => null);
if (message) {
interaction.message.delete()
}
const embed = new MessageEmbed()
.setDescription(`Ticket zamknięty przez <#${interaction.user.id}>`)
interaction.channel.send({embeds:[embed]})
setTimeout(() => {
const embed2 = new MessageEmbed()
.setDescription(`\`\`\`System kontroli ticketów po zamknięciu\`\`\``)
.setColor('YELLOW');
const buttonReopen = new MessageButton()
.setCustomId("reopenButton")
.setLabel("Otworz")
.setEmoji('🔓')
.setStyle('SECONDARY')
const buttonTranscript = new MessageButton()
.setCustomId("transcriptButton")
.setLabel("Transcript")
.setEmoji('📝')
.setStyle('SECONDARY')
const buttonDelete = new MessageButton()
.setCustomId("deleteButton")
.setLabel("Usun")
.setEmoji('⛔')
.setStyle('SECONDARY')
const row = new MessageActionRow()
.setComponents([ buttonTranscript, buttonReopen, buttonDelete])
interaction.channel.send({
embeds:[embed2],
components: [row]
})
}, 500)
} if(interaction.customId === 'close-nie'){
const message = await interaction.channel.messages.fetch(interaction.message.id).catch(() => null);
if (message) {
interaction.message.delete()
}
} if(interaction.customId === 'reopenButton') {
const usd = interaction.guild.members.cache.get(interaction.channel.topic)
const name = usd.user.username
interaction.channel.edit({
permissionOverwrites: [{
id: interaction.channel.topic,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL']
}, {
id:'949701839560011797' ,
deny: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
}, {
id: client.user.id,
allow: ['SEND_MESSAGES', 'VIEW_CHANNEL'],
}],
name: `ticket`
})
const embed = new MessageEmbed()
.setDescription(`Ticket został ponownie otworzony przez <#${interaction.user.id}> (${interaction.user.username})`)
.setColor('GREEN')
interaction.channel.send({embeds:[embed]})
const message = await interaction.channel.messages.fetch(interaction.message.id).catch(() => null);
if (message) {
interaction.message.delete()
}
}
// } if(interaction.customId === 'transcriptButton'){
// interaction.channel.send({ content: "Tworzenie zapisu..." })
// const user = await client.users.fetch(interaction.channel.topic)
// const transcript = await createTranscript(interaction.channel, {
// limit: -1,
// fileName: `ticket-${interaction.channel.topic}.html`,
// returnBuffer: false,
// })
// client.channels.cache.get("950383700904931368").send({
// files: [transcript]
// }).then(() => {
// interaction.channel.delete()
// })
// }
}
});
I'm using Agora to create screen-sharing action and I'm stuck not being able to get it to work on Safari/MacOS. The code below is working for Chrome and Firefox in both Mac/Windows. Every time I click on this IconButton, the error message is in the screenshot below.
What could be the issue? I've compared this to Agora's sample code, but cannot figure what caused this bug.
<IconButton color='primary' onClick={shareScreenClient ? clearScreenStream : startScreenStream}>
{shareScreenClient ? <StopScreenShareOutlinedIcon fontSize='large' /> : <ScreenShareOutlinedIcon fontSize='large' />}</IconButton>
//here's the def of startScreenStream.
const startScreenStream = (e) => {
e.preventDefault();
screenClient.current = AgoraRTC.createClient(agoraClientObj);
const channel = classroom;
const token = null;
screenClient.current.init(appID, () => {
screenClient.current.join(
token,
channel,
null,
(screenUid) => {
// Create the screen-sharing stream, screenStream.
setScreenStreamObj((x) => ({
...x,
streamId: screenUid,
}));
let screenStreamObj = {
streamID: screenUid,
audio: false,
video: false,
screen: true,
screenAudio: true,
};
if (audioDeviceId) screenStreamObj.microphoneId = audioDeviceId;
if (videoDeviceId) screenStreamObj.cameraId = videoDeviceId;
if (isFirefox) screenStreamObj.mediaSource = 'screen';
screenStream.current = AgoraRTC.createStream(screenStreamObj);
screenStream.current.setScreenProfile('480p_1');
screenStream.current.init(
() => {
screenStream.current.play('screen-share', { fit: 'cover' }, () => {
console.log('sharing screen');
setShareScreenClient(true);
});
screenClient.current.publish(screenStream.current, (err) => {
console.error('publish failed', err);
//clearScreenStream();
});
},
(err) => {
screenStream.current = null;
setScreenStreamObj({});
console.error('could not init stream', err);
}
);
},
(err) => {
screenClient.current = null;
console.error('Could not join channel', err);
}
);
});
}
I working on Testcases:
when i am running individual testcases it working fine but altogether if i am running its throwing error for 2 testscenarios.
my tsx code:
const onPasswordChange = useCallback((e) => {
setStatusAlert({});
setModel({ ...model, "password": e.target.value });
setPasswordError(null);
}, [setStatusAlert, setModel, setPasswordError]);
const showPasswordInput = useCallback((e) => {
e.preventDefault();
const emailIsEmpty = !model.email || model.email.length < 1;
setDisplayPasswordInput(!emailIsEmpty);
setEmailError(emailIsEmpty ? "Email is required" : null);
}, [model, setDisplayPasswordInput, setEmailError]);
My testcases:
describe("onPasswordChange", () => {
it("sets password to new value", async () => {
const expectedPassword = lorem.word();
mockedHttpHelper.get.mockImplementationOnce(jest.fn((params: IGetParams) => params.onGetSuccess({ data: { externalTypes: [] } } as AxiosResponse)));
await usingMount(
LoginFormComponent(defaultModelWithEmail),
async wrapper => {
await setTimeoutPromise(() => {
wrapper.find(LoginForm).find("LoginPasswordFormBody").invoke("onPasswordChange")({ target: { name: "password", value: expectedPassword } });
expect(wrapper.find(LoginForm).find("LoginPasswordFormBody").prop("model")).toEqual(expect.objectContaining({ password: expectedPassword }));
}, 100);
}
);
});
it("empties status alert", async () => {
const expectedError = lorem.word();
mockedHttpHelper.get.mockImplementationOnce(jest.fn((params: IGetParams) => params.onGetSuccess({ data: { externalTypes: [] } } as AxiosResponse)));
await usingMount(
<GrabStatusAlertContext>
<LoginForm model={defaultModelWithEmail} />
</GrabStatusAlertContext>,
async wrapper => {
await setTimeoutPromise(() => {
statusAlertContext.setStatusAlert({ color: "danger", text: expectedError });
expect(statusAlertContext.statusAlert).toEqual({ color: "danger", text: expectedError });
wrapper.find(LoginForm).find("LoginPasswordFormBody").invoke("onPasswordChange")({ target: { name: "password", value: expectedError } });
wrapper.update();
expect(statusAlertContext.statusAlert).toEqual({});
}, 100);
}
);
});
it("sets passwordError to null", async () => {
const passwordRequired = lorem.word();
mockedHttpHelper.get.mockImplementationOnce(jest.fn((params: IGetParams) => params.onGetSuccess({ data: { externalTypes: [] } } as AxiosResponse)));
await usingMount(
<GrabStatusAlertContext>
<LoginForm model={defaultModelWithEmail} />
</GrabStatusAlertContext>,
async wrapper => {
await setTimeoutPromise(() => {
// trigger passwordError by submitting an empty input and verify passwordError is not null
wrapper.find("form").simulate("submit");
expect(wrapper.find(LoginForm).find("LoginPasswordFormBody").prop("passwordError")).toEqual("Password is required");
wrapper.find(LoginForm).find(`input[type="password"]`).simulate("change", { target: { name: "password", value: passwordRequired } });
wrapper.update();
expect(wrapper.find(LoginForm).find("LoginPasswordFormBody").prop("passwordError")).toEqual(null);
}, 100);
}
);
});
});
Please help me any way i can resolve this issue.
I had the same problem i just gave the element an #id and used it in the find() function