• 设为首页
  • 点击收藏
  • 手机版
    手机扫一扫访问
    迪恩网络手机版
  • 关注官方公众号
    微信扫一扫关注
    迪恩网络公众号

ipfs-shipyard/rb-pinning-service-api: A rails app that implements the IPFS Pinni ...

原作者: [db:作者] 来自: 网络 收藏 邀请

开源软件名称:

ipfs-shipyard/rb-pinning-service-api

开源软件地址:

https://github.com/ipfs-shipyard/rb-pinning-service-api

开源编程语言:

Ruby 79.6%

开源软件介绍:

IPFS Pinning Service API

A rails app that implements the IPFS Pinning Service API.

Endpoints

The CRUD design of the pinning service API spec maps nicely onto the standard rails restful routing design with only a few minor tweaks needed to implement the full spec.

For the API, the default format is set to :json rather than HTML and CSRF protection is disabled, we've also nested the API routes under /api/v1 to seperate it from any html pages and allow deploying a v2 in the future without breaking compatibility with existing v1 clients.

TODO: implement authentication and access control via Authorization: Bearer <access-token>

The spec does not have any details around etag, gzip, last-modified and other headers that can help improve performance but these could be offered if the client supports them.

Create Pin

POST request to /pins go to pins#create, rails will automatically parse the body as json and convert into params. Although the spec does not nest the object in a pin object like the ActiveRecord pattern, the keys do map nicely onto fields on our Pin database table.

We store origins in a postgresql array field and meta in a postgresql jsonb field which gives us some validation for free, the only required field is cid so that validation is set on the Pin model and NOT NULL at the database level. The status is defaulted to queued on newly created Pin records.

Before saving the Pin to the database, we also set the address of our local IPFS node in the delegates field, fetched using ipfs id.

After successful validation, the following steps are made to communicate with local IPFS node via http to pin the CID (pseudo ipfs commands included inline):

  • set status to pinning
  • attempt to connect to each origin (ipfs swarm connect #{origin address})
  • pin the cid (ipfs pin add #{cid})
  • set status to pinned
  • if an error occurs then set status to failed

The spec says that a successful update results in a 202 (:accepted) response code with body of both the pin and it's status is then returned as JSON, rendered using the same jbuilder template as pins#show.

In rails the default is 200, as it appears that the spec assumes the ipfs actions will be happening in a job queue after the request has completed, although most http clients will accept and 2XX response as successful so this may not matter to much.

List Pins

GET request to /pins go to pins#index with optional url query params to filter responses. Default of 10 records per page (max 1000), always ordered by newest first (created_at DESC).

Pagination is not the usual ?page=1 but instead the client is expected to work out the next page by passing the created field of the last record in a response as before, so order must always be the by creation date for pagination to work. (An alternative option here would be offset which would allow pagination and ordering at the same time).

status can be one or more of the four allowed statuses (queued, pinning, pinned, failed), comma separated and if status is not provided (or invalid), then it defaults to pinned, this are passed straight to ActiveRecord to filter on: where(status: statuses).

One or more CID can be optionally passed, comma separated to cid, as they are case sensitive we can pass the array directly to ActiveRecord to filter on: where(cid: cids).

Clients can optionally filter results by name, which can be an exact or partial case sensitive match, we use a case insensitive ilike query in postgresql for this: where('name ilike ?', "%#{name}%").

Clients can optionally filter results by a key+value pair from the meta field, which is provided as json in the query parameter. Because we store meta in a jsonb field in postgresql, we can use the provided SQL function: where("meta->>? = ?", meta.key, meta.value). The spec is not clear on if the JSON stored in meta can be nested, we allow nested JSON to be stored on creation but the query may not work as expected if nested JSON is passed when filtering.

before and after allow optional filtering by created_at, we can pass the date through to postgresql: where('created_at < ?', before) and where('created_at > ?', after) if present.

count is the total number of records available for the given filters, ignoring the limit we we make a separate SQL query for that before loading the limited Pin records, if count is zero we can skip the second SQL query and return an empty array.

The response of an array of both the pin and it's status is then returned as JSON, rendered using the same jbuilder partial as #show along with count.

This endpoint doesn't hit the IPFS node and would make a good candidate for caching.

Get Pin

GET request to /pins/{id} go to pins#show which renders _pin_status.json.jbuilder or returns 404 if the pin doesn't exist.

This endpoint doesn't hit the IPFS node and would make a good candidate for caching.

Replace Pin

POST request to /pins/{id} go to pins#update, unlike the standard rails pattern of using PATCH (or PUT in older versions of rails) for updates so we need to specify an extra route, we also leave the regular PATCH route pointing to the same place but it could be disabled for completeness.

This endpoint accepts the same request body as pins#create, rails will automatically parse the body as json and convert into params. Although the spec does not nest the object in a pin object like the ActiveRecord pattern, the keys do map nicely onto fields on our Pin database table.

Unlike in standard CRUD rails, the spec says that rather than updating the pin of the given id, a new pin should be created and the old pin removed afterwards.

The user can modify an existing pin object via POST /pins/{id}. The new pin object id is returned in the PinStatus response. The old pin object is deleted automatically.

The response should return JSON for the newly created pin, not the pin of the given id.

It is unclear from the spec what should happen if the CID is the same as on the pin of the given id, for now we play it safe and remove the existing pin with ipfs pin rm #{cid} and recreate it with ipfs pin add #{cid} but we may be able to skip that step and just update the other fields on the database record.

It is also unclear when the pinning on the new CID fails, should the old pin still be deleted.

There is also a command in IPFS to update pins (ipfs pin update #{old-cid} #{new-cid}) which may be useful for here.

Similar to in pins#create, before saving the Pin to the database, we also set the address of our local IPFS node in the delegates field, fetched using ipfs id and then attempt to connect to each origin provided (ipfs swarm connect #{origin address})

The spec says that a successful update results in a 202 (:accepted) response code with body of both the pin and it's status is then returned as JSON, rendered using the same jbuilder template as pins#show.

In rails the default is 200, as it appears that the spec assumes the ipfs actions will be happening in a job queue after the request has completed, although most http clients will accept and 2XX response as successful so this may not matter to much.

Delete Pin

DELETE request to /pins/{id} go to pins#destroy, just like regular CRUD rails, we look up the Pin by id (404ing if not found), unpin the cid on the IPFS node (ipfs pin rm #{cid}) and then delete the record.

Successful deletion results in a 202 (:accepted) response with no body.

In rails the default is 200 (204 is also standard when there is no response body), as it appears that the spec assumes the ipfs actions will be happening in a job queue after the request has completed, although most http clients will accept and 2XX response as successful so this may not matter to much.

TODO

  • basic unit tests for pins model
  • info method on model
    • status_details
    • dag_size
    • raw_size
    • pinned_until
  • basic pinning client for testing
  • only unpin cid if this is the only pin with that CID
  • method for expiring pins after a certain amount of time (does it deleted it or update status?)

Notes

  • Does NOT support pinning IPNS names at the moment
  • Pagination is manual for the client, no need for pagination library or headers in server

Contributing

Contributions are welcome! This repository is part of the IPFS project and therefore governed by our contributing guidelines.

License

SPDX-License-Identifier: Apache-2.0 OR MIT




鲜花

握手

雷人

路过

鸡蛋
该文章已有0人参与评论

请发表评论

全部评论

专题导读
热门推荐
阅读排行榜

扫描微信二维码

查看手机版网站

随时了解更新最新资讯

139-2527-9053

在线客服(服务时间 9:00~18:00)

在线QQ客服
地址:深圳市南山区西丽大学城创智工业园
电邮:jeky_zhao#qq.com
移动电话:139-2527-9053

Powered by 互联科技 X3.4© 2001-2213 极客世界.|Sitemap