0

I want to access the timestamp.log file and fetch the last timestamp corresponding to an index name.

For example: if I pass logIndex = index-7.11.1-frontend1-endpoint-2021.02.24 as argument to fetchIndexTimeStamp it should return last timestamp corresponding to this logIndex i.e 3rd last line timestamp (2021-02-24T00:24:43.659Z)

timestamp.log looks as given below:

index-7.11.1-frontend2-endpoint-2021.02.24::2021-02-24T00:24:31.187Z
index-7.10.1-backend2-recommendation-2021.02.24::2021-02-24T00:23:36.793Z
index-7.10.1-backend1-config-mgmt-2021.02.24::2021-02-24T00:23:41.523Z
index-7.10.1-backend1-recommendation-2021.02.24::2021-02-24T00:23:41.523Z
index-7.10.1-backend2-migration-2021.02.24::2021-02-24T00:23:36.793Z
index-7.10.1-backend1-migration-2021.02.24::2021-02-24T00:23:41.523Z
index-7.11.1-frontend1-endpoint-2021.02.24::2021-02-24T00:24:29.659Z
index-7.11.1-frontend2-merlinui-2021.02.24::2021-02-24T00:03:08.988Z
index-7.11.1-frontend1-merlinui-2021.02.24::2021-02-24T00:02:07.705Z
index-7.11.1-frontend2-endpoint-2021.02.24::2021-02-24T00:24:31.187Z
index-7.10.1-backend2-recommendation-2021.02.24::2021-02-24T00:23:36.793Z
index-7.10.1-backend1-recommendation-2021.02.24::2021-02-24T00:23:41.523Z
index-7.10.1-backend1-config-mgmt-2021.02.24::2021-02-24T00:23:41.523Z
index-7.10.1-backend2-migration-2021.02.24::2021-02-24T00:23:36.793Z
index-7.10.1-backend1-migration-2021.02.24::2021-02-24T00:23:41.523Z
index-7.11.1-frontend1-endpoint-2021.02.24::2021-02-24T00:24:43.659Z
index-7.11.1-frontend1-merlinui-2021.02.24::2021-02-24T00:02:07.705Z
index-7.11.1-frontend2-merlinui-2021.02.24::2021-02-24T00:03:08.988Z

Here is my function to get the timestamp, but it's returning undefined:

const fs = require('fs')
module.exports = {
    fetchIndexTimeStamp: (logIndex) => {
        const dir = './logs/timestamp.log'
        fs.access(`${dir}`, fs.R_OK, (err) => {
            if(err) {
                console.log(err);
                if(err.code === 'ENOENT') {
                     // file does not exists
                    const writableStream = fs.createWriteStream(`${dir}`);
                    console.log('File does not exists !!')
                    const message = `${logIndex}::default`
                    writableStream.write(message + '\r\n')
                }
            }
            else {
                // file exists 
                let ans = undefined;
                const file = fs.readFileSync(`${dir}`, 'utf-8').split(/\r?\n/);
                file.forEach((line) => {
                    let temp = line.split("::");
                    if(temp[0].toString() === logIndex) {
                        ans = temp[1];
                    }
                })
                // console.log('data ', ans); // this is printing correct output
                return ans;
            }
        })
    }
}

const tmpstp = fetchIndexTimeStamp(logIndex); // gives undefined ??

Please let me know why the function is returning undefined??

T.J. Crowder
  • 1,031,962
  • 187
  • 1,923
  • 1,875
Rupesh
  • 840
  • 1
  • 12
  • 26
  • because your `return statement` at the wrong place – Sourabh Somani Feb 24 '21 at 10:19
  • You're returning from within the callback of `fs.access(...)`, not from within `fetchIndexTimeStamp(...)`. – sp00m Feb 24 '21 at 10:19
  • Because you have no `return` statement in `fetchIndexTimeStamp`. You have one in the `access` callback, but that just returns the value from the callback (where is it promptly ignored by `access`), not from `fetchIndexTimeStamp`. But more fundamentally, `fetchIndexTimeStamp` **can't** return information you get from `access`, since that information is only available *after* `fetchIndexTimeStamp` returns, see [the linked question's answers](https://stackoverflow.com/questions/14220321/how-do-i-return-the-response-from-an-asynchronous-call) for details. – T.J. Crowder Feb 24 '21 at 10:21
  • true fs.access is async method – Sourabh Somani Feb 24 '21 at 10:21
  • 1
    Your question has nothing to do with [tag:async-await]. Please don't over-tag. – T.J. Crowder Feb 24 '21 at 10:21
  • 2
    @SourabhSomani - Best to be careful there. :-) `fs.access` is an asynchronous function, but not an `async` function. – T.J. Crowder Feb 24 '21 at 10:22
  • @T.J.Crowder Sorry I mean asynchronous – Sourabh Somani Feb 24 '21 at 10:23
  • You can use `fs.accesssync` if you want to return from the method – Sourabh Somani Feb 24 '21 at 10:24
  • Note that using `access` and then `readFile`/`readFileSync` or similar is an anti-pattern involving a race condition. It's entirely possible for the file to exist when `access` checks for it and not exist when `readFile`/`readFileSync` tries to read it. As [the documentation says](https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback), just use `readFile/`readFileSync` and deal with the "not found" error. – T.J. Crowder Feb 24 '21 at 10:29
  • @SourabhSomani using ``fs.accessSync`` and returning from access method is still giving ```undefined``` – Rupesh Feb 24 '21 at 10:36
  • 1
    FWIW: https://pastebin.com/z4Ptgwpg but doing a synchronous file read is generally not best practice. – T.J. Crowder Feb 24 '21 at 10:38
  • @T.J.Crowder but the code you have in pastebin will look for first occurence of logIndex and will return the corresponding value but what we want is last value corresponding to that particular logIndex i.e first occurence from end. Plz look at the example I updated in question I think using a var to store the value would work but that's not efficient to update the var each time. – Rupesh Feb 24 '21 at 10:49
  • Thanks a lot @T.J.Crowder, it worked but to make it efficient can't we read from end of file only? – Rupesh Feb 24 '21 at 10:52
  • 1
    @Rupesh - Re first/last - sorry about that, I missed that nuance. *"...but that's not efficient to update the var each time"* That's nothing compared to reading the file. But if it worries you, loop backward: `for (let n = file.length - 1; n >= 0; --n) { const line = file[n]; /*...*/ }` – T.J. Crowder Feb 24 '21 at 11:00
  • 1
    It's entirely possible to read just the end of the file, see the [`read` function](https://nodejs.org/api/fs.html#fs_fs_read_fd_buffer_offset_length_position_callback)'s `position` parameter. If you know the average size of a line and the average number of lines you'll need to find the value you want, you could read a chunk at the end, look for the corresponding line, then read a chunk before it, etc. The chunks won't be aligned to line boundaries, but you can handle that. It will be more involved but for **large** files where you expect the data to be at the end, it'll be more efficient. – T.J. Crowder Feb 24 '21 at 11:01
  • 1
    Thanks a ton @T.J.Crowder!! It's very helpful for me. – Rupesh Feb 24 '21 at 11:05

0 Answers0