(About IPFS)addAll with { wrapWithDirectory: true } is very slow - ipfs

const sources = files.map((file) => ({ path: `${file.index}${extension}`, content: file.buffer }));
for await (const result of ipfs.addAll(sources, { wrapWithDirectory: true })) {
Logger.log(`Uploaded: ${result.path}`);
if (result.path === "") {
rootCid = result.cid.toString();
}
}
const sources = files.map((file) => ({ path: `root/${file.index}${extension}`, content: file.buffer }));
for await (const result of ipfs.addAll(sources)) {
Logger.log(`Uploaded: ${result.path}`);
if (result.path === "root") {
rootCid = result.cid.toString();
}
}
The rootCid will be the same for both of the above codes, but { wrapWithDirectory: true } is very slower. Why is this?

This is because the execution time of ipfs' api method addAll is O(n) where n is the number of items in your input array
In other words, the more items you wish to add at once the longer it takes because each one creates an API call to add the item and each call must be awaited

Related

Merge mixin in vue

I'm working in vue/quasar application.
I've my mixin like this in my view.cshtml
var mixin1 = {
data: function () {
return { data1:0,data2:'' }
}
,
beforeCreate: async function () {
...}
},
methods: {
addformulaire(url) {
},
Kilometrique() { }
}
}
And I want merge with my content in js file (it's to centralize same action an severals cshtml)
const nomeMixins = {
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
computed: {
libmntpiece(v) { return "toto"; }
},
methods: {
findinfcomplemtX3(cdecltx3, cdedocx3) {
},
preremplissagex3: async function (cdecltx3, cdedocx3) {
}
}
}
};
I want merge this 2 miwin in one. But when I try assign or var mixin = { ...mixin1, ...nomeMixins };
I've only mixin1 nothing about methods,data from my js file nomeMixins but merging failed cause I've same key in my json object. I'm trying to make a foreach but failed too
Someone try to merge to mixin / json object with same key in the case you've no double child property ?
You cant merge mixins in that way. the spread syntax will overwrite keys e.g data, computed, methods etc and final result will not be suitable for your purpose.
refer documentation for adding mixins in your component. Also note that You can easily add multiple mixins in any component, so I don't think combination of two mixins will be any useful.
UPDATE
reply to YannickIngenierie answer and pointing out mistakes in this article
Global Mixins are not declared like this
// not global mixin; on contrary MyMixin is local
// and only available in one component.
new Vue({
el: '#demo',
mixins: [MyMixin]
});
Local Mixins are not declared like this
// NOT local mixin; on contrary its global Mixin
// and available to all components
const DataLoader = Vue.mixin({....}}
Vue.component("article-card", {
mixins: [DataLoader], // no need of this
template: "#article-card-template",
created() {
this.load("https://jsonplaceholder.typicode.com/posts/1")
}
});
Point is refer documentation first before reading any article written by some random guy, including me. Do slight comparison what he is saying whats in documentation.
After working and searching... I find this one And understand that I can add directly mixin in my compoment (don't laught I'm begging with vue few months ago)
my custommiwin.js
const DataLoader = Vue.mixin({
data: function () {
return { loadingcdt: false, lstclt: [], filterclient: [], loadingdoc: false, lstdoc: [], filterdoc: [] }
},
methods: {
filterClt: async function (val, update, abort) {
if (val.length < 3) { abort(); return; }
else {//recherche
this.loadingcdt = true;
let res = await axios...
this.loadingcdt = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterclient = this.lstclt.filter(v => v.libelle.toLowerCase().indexOf(needle) > -1 || v.id.toLowerCase().indexOf(needle) > -1);
})
},
filterDocument: async function (val, update, abort, cdecltx3) {
if (!cdecltx3 || val.length < 3) { abort(); return; }
else {//recherche
this.loadingdoc = true;
let res = await axios({ ...) }
this.loadingdoc = false;
}
update(() => {
const needle = val.toLowerCase();
this.filterdoc = this.lstdoc.filter(v => v.id.toLowerCase().indexOf(needle) > -1);
})
},
}
});
and in my compoment.js I add this
mixins: [DataLoader],
I include all my js file in my cshtml file

ipfs.add() returns Object [AsyncGenerator] {}

I am unable to figure out what mistake i have done in the code
Whenever i am calling api, ipfs.add('hello') returns [object AsyncGenerator]
https://gateway.ipfs.io/ipfs/[object AsyncGenerator]
const addFile = async () => {
const Added = await ipfs.add('hello');
return Added;
}
const fileHash = await addFile();
return fileHash;
You can iterate over the result of .add() like so:
for await (const item of Added) {
console.log('item', item)
}
item { path: 'QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX',
cid: CID(QmWfVY9y3xjsixTgbd9AorQxH7VtMpzfx2HaWtsoUYecaX), size: 13 }

<Connect /> re-renders onSubscriptionMsg, but not with new data

I have a really simple component using Connect from aws-amplify-react
const EmployeeExpensesTable = () => {
const [user, setUser] = useState(null)
useEffect(() => { Auth.currentAuthenticatedUser().then(user => setUser(user)) }, [])
console.log(user)
if(!user) { return null }
return (
<Connect
query={graphqlOperation(queries.listTransactions, { owner: user.username })}
subscription={graphqlOperation(subscriptions.onCreateTransaction, { owner: user.username })}
onSubscriptionMsg={(prev, { onCreateTransaction }) => {
console.log('oncreatetransaction:', onCreateTransaction)
console.log('prev', prev)
return onCreateTransaction
}}
>
{
({ data: { listTransactions }, loading, errors }) => {
console.log('transactions', listTransactions)
if (errors.length) return (<h3>Error</h3>)
if (loading || !listTransactions) return (<p>loading...</p>)
return (<core.components.Table data={listTransactions.items} />)
}
}
</Connect>
)
}
export default EmployeeExpensesTable
I have an external ETL process that adds transactions to the DynamoDB table. The subscription is firing and my oncreatetransaction message is being displayed with the new data, and the Connect component re-renders, but it renders using it's original data, not the new data. What am I doing wrong?
Turns out that onSubscriptionMsg is like the reducer for the Connect component's state. You are given the previous value and the new value to the function and you need to return the new state.
onSubscriptionMsg={(prev, data) => ({
listTransactions: {
items: [...prev.listTransactions.items.slice(-9), data.onCreateTransaction ]
}
})
The above works great for me. The .slice(-9) is because I only care about the last 10 rows that were added.

NodeJS: Array and/or JSON filled with \r\n when using promises

My server is supposed to send me back some data (stored as json) read when asked. To avoid blocking communications, I set-up 2 promises: one to read a file:
function readingfile(survey) {
return new Promise(
function (data_read, err) {
fs.stat(`./data/${survey}.json`, function (err, stat) {
if (err == null) {
fs.readFile(`./data/${survey}.json`, 'utf8', (err, data) => {
data_read((data))
})
} else
console.error(`./data/${survey}.json doesnt exist`)
})
})
}
and one to read all files from a user:
function readingusersurveys(user) {
let questionnaires = [];
let count = 0;
return new Promise(
function (data_read, err) {
user.surveys.forEach((survey) => {
readingfile(survey).then(function (all_surveys) {
count++;
//console.log((all_surveys)) //ok here
questionnaires.push((all_surveys))
if (count == user.surveys.length) {
console.log((questionnaires)) //not ok here (wtf)
data_read((questionnaires))
}
})
})
})
}
and the code snippet that send the data:
[...]
readingusersurveys(req.user).then(function (all_surveys) {
//console.log(all_surveys)
questionnaires.push((all_surveys))
console.log(questionnaires)
if (questionnaires != null) {
res.status(200).json({
questionnaires
});
} else {
res.status(500).json({});
}
})
but when readingusersurveys() return the data read, it get filled with tons of \r\n making the file unreadable. If I try to place a JSON.parse somewhere, I either: enter a infinite loop or the data become unreadable/undefined (eg: {"asset": ["value"]} become {"asset": [Object]}).
I have tried to place a JSON.parse pretty much everywhere to change comportement but no luck. Any idea how to get rid of \r\n and/or what's missing in my code ? :/
After many tries, I found out that it wasn't the JSON.parse the problem but questionnaire.push. It wasn't doing what I though it was doing(adding 2 json array together).
Added the JSON.parse here
function readingusersurveys(user) {
let questionnaires = [];
let count = 0;
return new Promise(
function (data_read, err) {
user.surveys.forEach((survey) => {
readingfile(survey).then(function (all_surveys) {
count++;
questionnaires.push(JSON.parse(all_surveys)) // <-- HERE
if (count == user.surveys.length) {
data_read((questionnaires)) //<-- array of JSON at this point
}
})
})
})
}
[...]
readingusersurveys(req.user).then(function (all_surveys) {
questionnaires = (all_surveys) //<-- pushing an array of JSON into another array was what created problems
if (questionnaires != null) {
res.status(200).json({
questionnaires
});
} else {
res.status(500).json({});
}
})
If I wanted to do a loop there and add more surveys, I needed to use concat() instead
if (questionnaires[0] == null)
questionnaires = all_surveys
else
questionnaires = questionnaires.concat(all_surveys)

Transform Request to Autoquery friendly

We are working with a 3rd party grid (telerik kendo) that has paging/sorting/filtering built in. It will send the requests in a certain way when making the GET call and I'm trying to determine if there is a way to translate these requests to AutoQuery friendly requests.
Query string params
Sort Pattern:
sort[{0}][field] and sort[{0}][dir]
Filtering:
filter[filters][{0}][field]
filter[filters][{0}][operator]
filter[filters][{0}][value]
So this which is populated in the querystring:
filter[filters][0][field]
filter[filters][0][operator]
filter[filters][0][value]
would need to be translated to.
FieldName=1 // filter[filters][0][field]+filter[filters][0][operator]+filter[filters][0][value] in a nutshell (not exactly true)
Should I manipulate the querystring object in a plugin by removing the filters (or just adding the ones I need) ? Is there a better option here?
I'm not sure there is a clean way to do this on the kendo side either.
I will explain the two routes I'm going down, I hope to see a better answer.
First, I tried to modify the querystring in a request filter, but could not. I ended up having to run the autoqueries manually by getting the params and modifying them before calling AutoQuery.Execute. Something like this:
var requestparams = Request.ToAutoQueryParams();
var q = AutoQueryDb.CreateQuery(requestobject, requestparams);
AutoQueryDb.Execute(requestobject, q);
I wish there was a more global way to do this. The extension method just loops over all the querystring params and adds the ones that I need.
After doing the above work, I wasn't very happy with the result so I investigated doing it differently and ended up with the following:
Register the Kendo grid filter operations to their equivalent Service Stack auto query ones:
var aq = new AutoQueryFeature { MaxLimit = 100, EnableAutoQueryViewer=true };
aq.ImplicitConventions.Add("%neq", aq.ImplicitConventions["%NotEqualTo"]);
aq.ImplicitConventions.Add("%eq", "{Field} = {Value}");
Next, on the grid's read operation, we need to reformat the the querystring:
read: {
url: "/api/stuff?format=json&isGrid=true",
data: function (options) {
if (options.sort && options.sort.length > 0) {
options.OrderBy = (options.sort[0].dir == "desc" ? "-" : "") + options.sort[0].field;
}
if (options.filter && options.filter.filters.length > 0) {
for (var i = 0; i < options.filter.filters.length; i++) {
var f = options.filter.filters[i];
console.log(f);
options[f.field + f.operator] = f.value;
}
}
}
Now, the grid will send the operations in a Autoquery friendly manner.
I created an AutoQueryDataSource ts class that you may or may not find useful.
It's usage is along the lines of:
this.gridDataSource = AutoQueryKendoDataSource.getDefaultInstance<dtos.QueryDbSubclass, dtos.ListDefinition>('/api/autoQueryRoute', { orderByDesc: 'createdOn' });
export default class AutoQueryKendoDataSource<queryT extends dtos.QueryDb_1<T>, T> extends kendo.data.DataSource {
private constructor(options: kendo.data.DataSourceOptions = {}, public route?: string, public request?: queryT) {
super(options)
}
defer: ng.IDeferred<any>;
static exportToExcel(columns: kendo.ui.GridColumn[], dataSource: kendo.data.DataSource, filename: string) {
let rows = [{ cells: columns.map(d => { return { value: d.field }; }) }];
dataSource.fetch(function () {
var data = this.data();
for (var i = 0; i < data.length; i++) {
//push single row for every record
rows.push({
cells: _.map(columns, d => { return { value: data[i][d.field] } })
})
}
var workbook = new kendo.ooxml.Workbook({
sheets: [
{
columns: _.map(columns, d => { return { autoWidth: true } }),
// Title of the sheet
title: filename,
// Rows of the sheet
rows: rows
}
]
});
//save the file as Excel file with extension xlsx
kendo.saveAs({ dataURI: workbook.toDataURL(), fileName: filename });
})
}
static getDefaultInstance<queryT extends dtos.QueryDb_1<T>, T>(route: string, request: queryT, $q?: ng.IQService, model?: any) {
let sortInfo: {
orderBy?: string,
orderByDesc?: string,
skip?: number
} = {
};
let opts = {
transport: {
read: {
url: route,
dataType: 'json',
data: request
},
parameterMap: (data, type) => {
if (type == 'read') {
if (data.sort) {
data.sort.forEach((s: any) => {
if (s.field.indexOf('.') > -1) {
var arr = _.split(s.field, '.')
s.field = arr[arr.length - 1];
}
})
}//for autoquery to work, need only field names not entity names.
sortInfo = {
orderByDesc: _.join(_.map(_.filter(data.sort, (s: any) => s.dir == 'desc'), 'field'), ','),
orderBy: _.join(_.map(_.filter(data.sort, (s: any) => s.dir == 'asc'), 'field'), ','),
skip: 0
}
if (data.page)
sortInfo.skip = (data.page - 1) * data.pageSize,
_.extend(data, request);
//override sorting if done via grid
if (sortInfo.orderByDesc) {
(<any>data).orderByDesc = sortInfo.orderByDesc;
(<any>data).orderBy = null;
}
if (sortInfo.orderBy) {
(<any>data).orderBy = sortInfo.orderBy;
(<any>data).orderByDesc = null;
}
(<any>data).skip = sortInfo.skip;
return data;
}
return data;
},
},
requestStart: (e: kendo.data.DataSourceRequestStartEvent) => {
let ds = <AutoQueryKendoDataSource<queryT, T>>e.sender;
if ($q)
ds.defer = $q.defer();
},
requestEnd: (e: kendo.data.DataSourceRequestEndEvent) => {
new DatesToStringsService().convert(e.response);
let ds = <AutoQueryKendoDataSource<queryT, T>>e.sender;
if (ds.defer)
ds.defer.resolve();
},
schema: {
data: (response: dtos.QueryResponse<T>) => {
return response.results;
},
type: 'json',
total: 'total',
model: model
},
pageSize: request.take || 40,
page: 1,
serverPaging: true,
serverSorting: true
}
let ds = new AutoQueryKendoDataSource<queryT, T>(opts, route, request);
return ds;
}
}