Skip to content

Commit

Permalink
feat: file peers health
Browse files Browse the repository at this point in the history
  • Loading branch information
hacdias committed Jul 27, 2018
1 parent 4759125 commit f3a1564
Show file tree
Hide file tree
Showing 5 changed files with 182 additions and 0 deletions.
148 changes: 148 additions & 0 deletions src/bundles/files-provs.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import { createSelector } from 'redux-bundler'

export default function (opts) {
opts = opts || {}
opts.concurrency = opts.concurrency || 5

const defaultState = {
provs: {},
queue: [],
resolving: []
}

return {
name: 'filesProvs',

reducer (state = defaultState, action) {
if (action.type === 'FILES_PROVS_QUEUED') {
const hashes = action.payload
const provs = {}

hashes.forEach(hash => {
provs[hash] = {
state: 'queued'
}
})

return {
...state,
queue: state.queue.concat(hashes),
provs: {
...state.provs,
...provs
}
}
}

if (action.type === 'FILES_PROVS_RESOLVE_STARTED') {
const { hash } = action.payload

return {
...state,
queue: state.queue.filter(h => hash !== h),
resolving: state.resolving.concat(hash),
provs: {
...state.provs,
[hash]: {
state: 'resolving'
}
}
}
}

if (action.type === 'FILES_PROVS_RESOLVE_FINISHED') {
const { hash, count } = action.payload

return {
...state,
resolving: state.resolving.filter(h => h !== hash),
provs: {
...state.provs,
[hash]: {
state: 'resolved',
count: count
}
}
}
}

if (action.type === 'FILES_PROVS_RESOLVE_FAILED') {
const { hash, error } = action.payload

return {
...state,
resolving: state.resolving.filter(h => h !== hash),
provs: {
...state.provs,
[hash]: {
state: 'failed',
error: error
}
}
}
}

return state
},

selectFilesProvs: state => state.filesProvs.provs,
selectFilesProvsQueuing: state => state.filesProvs.queue,
selectFilesProvsResolving: state => state.filesProvs.resolving,

doFindProvs: hash => async ({ dispatch, getIpfs }) => {
dispatch({ type: 'FILES_PROVS_RESOLVE_STARTED', payload: { hash } })

const ipfs = getIpfs()
let count

try {
const res = await ipfs.dht.findprovs(hash, { timeout: '30s', 'num-providers': 5 })
count = res.filter(t => t.Type === 4).length
} catch (err) {
return dispatch({
type: 'FILES_PROVS_RESOLVE_FAILED',
payload: { hash, error: err }
})
}

dispatch({
type: 'FILES_PROVS_RESOLVE_FINISHED',
payload: { hash, count }
})
},

reactFindProvs: createSelector(
'selectIpfsReady',
'selectFilesProvsQueuing',
'selectFilesProvsResolving',
(ipfsReady, queuing, resolving) => {
if (ipfsReady && queuing.length && resolving.length < opts.concurrency) {
return {
actionCreator: 'doFindProvs',
args: [ queuing[0] ]
}
}
}
),

reactFindProvsQueue: createSelector(
'selectFiles',
'selectFilesProvs',
(files, filesProvs) => {
if (!files || files.type !== 'directory') {
return
}

const payload = files.content.reduce((acc, { hash }) => {
if (!filesProvs[hash]) {
return [...acc, hash]
} else {
return acc
}
}, [])

return { type: 'FILES_PROVS_QUEUED', payload }
}
)
}
}
2 changes: 2 additions & 0 deletions src/bundles/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import peerLocationsBundle from './peer-locations'
import routesBundle from './routes'
import redirectsBundle from './redirects'
import filesBundle from './files'
import filesProvsBundle from './files-provs'
import configBundle from './config'
import configSaveBundle from './config-save'
import navbarBundle from './navbar'
Expand All @@ -27,6 +28,7 @@ export default composeBundles(
routesBundle,
redirectsBundle,
filesBundle(),
filesProvsBundle(),
configBundle,
configSaveBundle,
navbarBundle
Expand Down
15 changes: 15 additions & 0 deletions src/files/FilesPage.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ class FilesPage extends React.Component {
filesErrors: PropTypes.array.isRequired,
filesPathFromHash: PropTypes.string,
writeFilesProgress: PropTypes.number,
filesProvs: PropTypes.object,
gatewayUrl: PropTypes.string.isRequired,
navbarWidth: PropTypes.number.isRequired,
doUpdateHash: PropTypes.func.isRequired,
Expand Down Expand Up @@ -95,6 +96,7 @@ class FilesPage extends React.Component {
render () {
const {
files,
filesProvs,
writeFilesProgress,
navbarWidth,
doFilesDismissErrors,
Expand All @@ -104,6 +106,18 @@ class FilesPage extends React.Component {
filesErrors: errors
} = this.props

if (files && files.content) {
files.content = files.content.map(file => {
if (filesProvs[file.hash] && filesProvs[file.hash].count) {
file.peers = filesProvs[file.hash].count
} else {
file.peers = 0
}

return file
})
}

return (
<div data-id='FilesPage'>
<Helmet>
Expand Down Expand Up @@ -163,6 +177,7 @@ export default connect(
'doFilesNavigateTo',
'selectFiles',
'selectFilesErrors',
'selectFilesProvs',
'selectGatewayUrl',
'selectWriteFilesProgress',
'selectNavbarWidth',
Expand Down
16 changes: 16 additions & 0 deletions src/files/file/File.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,9 @@ import filesize from 'filesize'
import Checkbox from '../../components/checkbox/Checkbox'
import FileIcon from '../file-icon/FileIcon'
import Tooltip from '../../components/tooltip/Tooltip'
import PeersSmallIcon from '../../icons/GlyphPeersSmall'
import PeersMediumIcon from '../../icons/GlyphPeersMedium'
import PeersLargeIcon from '../../icons/GlyphPeersLarge'
import { DropTarget, DragSource } from 'react-dnd'
import { NativeTypes } from 'react-dnd-html5-backend'
import { join, basename } from 'path'
Expand All @@ -16,6 +19,7 @@ function File ({
hash,
name,
path,
peers,
type,
size,
onSelect,
Expand Down Expand Up @@ -65,6 +69,17 @@ function File ({
</div>
)}
<div className='size pa2 w-10 monospace dn db-l'>{size}</div>
<div className='pa2 w3 f6 dn db-l'>
{ peers <= 1 &&
<PeersSmallIcon fill='#F26148' width='2.5rem' />
}
{ peers > 1 && peers < 5 &&
<PeersMediumIcon fill='#F38F20' width='2.5rem' />
}
{ peers >= 5 &&
<PeersLargeIcon className='fill-aqua' width='2.5rem' />
}
</div>
</div>
))
}
Expand All @@ -75,6 +90,7 @@ File.propTypes = {
path: PropTypes.string.isRequired,
size: PropTypes.number.isRequired,
hash: PropTypes.string.isRequired,
peers: PropTypes.number.isRequired,
selected: PropTypes.bool.isRequired,
onSelect: PropTypes.func.isRequired,
onNavigate: PropTypes.func.isRequired,
Expand Down
1 change: 1 addition & 0 deletions src/files/files-list/FilesList.js
Original file line number Diff line number Diff line change
Expand Up @@ -289,6 +289,7 @@ class FileList extends React.Component {
Size {this.sortByIcon(ORDER_BY_SIZE)}
</span>
</div>
<div className='ph2 f6 w3 dn db-l'>Health</div>
</header>
{this.files}
{this.selectedMenu}
Expand Down

0 comments on commit f3a1564

Please sign in to comment.