I am not able to fetch data in my IntentHandler class. My Goal is select Todo from the CoreData list and display it in Widget.
I am trying to display a list from CoreData in Widget Intent and I am expecting to resolve this issue.
extension IntentHandler : ConfigurationIntentHandling {
func provideTodoNameOptionsCollection(for intent: ConfigurationIntent, searchTerm: String?, with completion: #escaping (INObjectCollection<TodoData>?, Error?) -> Void) {
var arrTodoData = [TodoData]()
coreDH.getAllTodos().forEach { todos in
let todoIntent = TodoData(identifier: todos.id?.uuidString, display: todos.name ?? "")
arrTodoData.append(todoIntent)
}
let collection = INObjectCollection(items: arrTodoData)
completion(collection, nil)
}
}
class IntentHandler: INExtension{
let coreDH = CoreDataHandler.shared
override func handler(for intent: INIntent) -> Any {
// This is the default implementation. If you want different objects to handle different intents,
// you can override this and return the handler you want for that particular intent.
return self
}
}
If your IntentHandler doesn't get called:
Ensure your Widget uses IntentConfiguration not StaticConfiguration
Ensure your time line provider conforms to IntentTimelineProvider
Run the app scheme, then run the intent scheme, you should be able to debug and breakpoints would work.
Widgets Code-along, part 3: Advancing timelines (5:31)
Add Configuration and Intelligence to Your Widgets
If you need to share data between your app and extension:
App's data is sandboxed and is not accessible by extension
Configure App Groups and you could create core data file in the shared container to be able to access in your extension
If App and Extension use exactly the same data you could use the same sqlite file in the shared container (both app and extension would have access to it)
If App and Extension use different data and there is only a small portion that is common, then use History Tracking
Configuring App Groups
Consuming Relevant Store Changes
I am implementing a Twitter-like application in Erlang. I have both its distributed and non-distributed implementations. I am doing a benchmark but it seems I cannot find a way to send parallel requests to each user process for the distributed implementation. I am using a lists:foreach function to send "get tweets" to a list of client processes.My understanding is that the lists:foreach function steps into each element of the list one at a time realizing a sequential behavior which ultimately makes my distributed implementation result in an equal execution time with the non-distributed implementation. Is it possible to send the "get tweets" requests to different client processes all at once? This to me seems like a rather specific case and it has been difficult to search for a solution inside and outside StackOverflow.
test_get_tweets_Bench() ->
{ServerPid, UserInfos} = initializeForBench_server(),
run_benchmark("timeline",
fun () ->
lists:foreach(fun (_) ->
UserChoice = pick_random(UserInfos),
server:get_tweets(element(2, UserChoice), element(1, UserChoice), 1)
end,
lists:seq(1, 10000))
end,
30).
pick_random(List) ->
lists:nth(rand:uniform(length(List)), List).
userinfos is a list of the following form: [{userId,client_process},...]
After trying rpc:pmap instead of the lists:foreach, my benchmark has become approximately 3 times slower. The changes are as follows:
test_get_tweets_Bench2() ->
{ServerPid, UserInfos} = initializeForBench_server(),
run_benchmark("get_tweets 2",
fun () ->
rpc:pmap({?MODULE,do_apply},
[fun (_) ->
UserChoice = pick_random(UserInfos),
server:get_tweets(element(2, UserChoice), element(1, UserChoice), 1)
end],
lists:seq(1, 10000))
end,
30).
pick_random(List) ->
lists:nth(rand:uniform(length(List)), List).
do_apply(X,F)->
F(X).
I thought rpc:pmap would make my benchmark faster as it would send the get_tweet requests in parallel.
Below is my server module which is the API between my benchmark and my Twitter-like application. The API sends the requests from my benchmark to my Twitter-like application.
%% This module provides the protocol that is used to interact with an
%% implementation of a microblogging service.
%%
%% The interface is design to be synchrounous: it waits for the reply of the
%% system.
%%
%% This module defines the public API that is supposed to be used for
%% experiments. The semantics of the API here should remain unchanged.
-module(server).
-export([register_user/1,
subscribe/3,
get_timeline/3,
get_tweets/3,
tweet/3]).
%%
%% Server API
%%
% Register a new user. Returns its id and a pid that should be used for
% subsequent requests by this client.
-spec register_user(pid()) -> {integer(), pid()}.
register_user(ServerPid) ->
ServerPid ! {self(), register_user},
receive
{ResponsePid, registered_user, UserId} -> {UserId, ResponsePid}
end.
% Subscribe/follow another user.
-spec subscribe(pid(), integer(), integer()) -> ok.
subscribe(ServerPid, UserId, UserIdToSubscribeTo) ->
ServerPid ! {self(), subscribe, UserId, UserIdToSubscribeTo},
receive
{_ResponsePid, subscribed, UserId, UserIdToSubscribeTo} -> ok
end.
% Request a page of the timeline of a particular user.
% Request results can be 'paginated' to reduce the amount of data to be sent in
% a single response. This is up to the server.
-spec get_timeline(pid(), integer(), integer()) -> [{tweet, integer(), erlang:timestamp(), string()}].
get_timeline(ServerPid, UserId, Page) ->
ServerPid ! {self(), get_timeline, UserId, Page},
receive
{_ResponsePid, timeline, UserId, Page, Timeline} ->
Timeline
end.
% Request a page of tweets of a particular user.
% Request results can be 'paginated' to reduce the amount of data to be sent in
% a single response. This is up to the server.
-spec get_tweets(pid(), integer(), integer()) -> [{tweet, integer(), erlang:timestamp(), string()}].
get_tweets(ServerPid, UserId, Page) ->
ServerPid ! {self(), get_tweets, UserId, Page},
receive
{_ResponsePid, tweets, UserId, Page, Tweets} ->
Tweets
end.
% Submit a tweet for a user.
% (Authorization/security are not regarded in any way.)
-spec tweet(pid(), integer(), string()) -> erlang:timestamp().
tweet(ServerPid, UserId, Tweet) ->
ServerPid ! {self(), tweet, UserId, Tweet},
receive
{_ResponsePid, tweet_accepted, UserId, Timestamp} ->
Timestamp
end.
In Erlang, a message is exchanged form a process A to a process B. There is no feature available like a broadcast, or a selective broadcast. In your application I see 3 steps:
send a request to get the tweets from the users,
the user process prepare the answer and send it back to the requester
the initial process collects the answers
Sending the requests to the user processes and collecting the tweets (steps 1 and 3) cannot use parallelism. Of course you can use multiple processes to send the requests and collect the answers, up to 1 per user, but I guess that it is not the subject of your question.
What is feasible, is to ensure that the 3 steps are not done in sequence for each user process, but in parallel. I guess that the function server:get_tweets is responsible to send the request and collect the answers. If I am correct (I cannot know since You don't provide the code, and you ignore the returned values), you can use parallelism by splitting this function in 2, the first send the requests, the second collects the answers. (here is an example of code, I don't have tried or even compiled, so consider it with care :o)
test_get_tweets_Bench() ->
{ServerPid, UserInfos} = initializeForBench_server(),
run_benchmark("timeline",
fun () ->
% send the requests
List = lists:map(fun (_) ->
{UserId,Pid} = pick_random(UserInfos),
Ref = server:request_tweets(Pid,UserId),
{Ref,UserId}
end,
lists:seq(1, 10000)),
% collects the answers
collect(L,[])
end,
30).
collect([],Result) -> {ok,Result};
collect(List,ResultSoFar) ->
receive
{Ref,UserId,Tweets} ->
{ok,NewList} = remove_pending_request(Ref,UserId,List),
collect(Newlist,[{UserId,Tweets}|ResultSoFar])
after ?TIMEOUT
{error,timeout,List,ResultSoFar}
end.
remove_pending_request(Ref,UserId,List) ->
{value,{Ref,UserId},NewList} = lists:keytake(Ref,1,List),
{ok,NewList}.
pick_random(List) ->
lists:nth(rand:uniform(length(List)), List).
This is my other attempt at implementing a parallel benchmark which does not achieve any speed up.
get_tweets(Sender, UserId, Node) ->
server:get_tweets(Node, UserId, 0),
Sender ! done_get_tweets.
test_get_tweets3() ->
{_ServerId, UserInfos} = initializeForBench_server(),
run_benchmark("parallel get_tweet",
fun () ->
lists:foreach(
fun (_) ->
{UserId,Pid} = pick_random(UserInfos),
spawn(?MODULE, get_tweets, [self(), UserId, Pid])
end,
lists:seq(1, ?NUMBER_OF_REQUESTS)),
lists:foreach(fun (_) -> receive done_get_tweets -> ok end end, lists:seq(1, ?NUMBER_OF_REQUESTS))
end,
?RUNS).
I'm trying to use Yesod to build a simple web site and I'm starting with the code from Max Tagher's excellent intro on Youtube, YesodScreencast. I've forked his code from GitHub, and I would like to add a date to the posting to indicate when it was published, but I'm running into the problem that I can't quite figure out given my low experience with Haskell and beginner's experience with Yesod. I've been unable to find an answer via the Googleplex.
Yesod provides a native dayField in Yesod.Form.Fields, so I thought that all I needed to do was to add the postdate Field in BlogPost the following to config/models using Day:
BlogPost
title Text
postdate Day
article Markdown
and add it to the blogPostForm in PostNew.hs:
blogPostForm :: AForm Handler BlogPost
blogPostForm = BlogPost
<$> areq textField (bfs ("Title" :: Text)) Nothing
<*> areq dayField (bfs ("Postdate" :: Day)) Nothing
<*> areq markdownField (bfs ("Article" :: Text)) Nothing
When this compiles I get the following error message:
Handler/Home.hs:16:11:
Could not deduce (blaze-markup-0.6.3.0:Text.Blaze.ToMarkup Day)
arising from a use of ‘toHtml’
from the context (PersistEntity BlogPost)
bound by a pattern with constructor
Entity :: forall record.
PersistEntity record =>
Key record -> record -> Entity record,
in a lambda abstraction
at Handler/Home.hs:16:11-34
In the first argument of ‘asWidgetT GHC.Base.. toWidget’, namely
‘toHtml (blogPostPostdate post_apZp)’
In a stmt of a 'do' block:
(asWidgetT GHC.Base.. toWidget)
(toHtml (blogPostPostdate post_apZp))
In the expression:
do { (asWidgetT GHC.Base.. toWidget)
((blaze-markup-0.6.3.0:Text.Blaze.Internal.preEscapedText
GHC.Base.. Data.Text.pack)
"<h4><li><a href=\"");
(getUrlRenderParams
>>=
(\ urender_apZq
-> (asWidgetT GHC.Base.. toWidget)
(toHtml
(\ u_apZr -> urender_apZq u_apZr [] (PostDetailsR id_apZo)))));
(asWidgetT GHC.Base.. toWidget)
((blaze-markup-0.6.3.0:Text.Blaze.Internal.preEscapedText
GHC.Base.. Data.Text.pack)
"\">");
(asWidgetT GHC.Base.. toWidget)
(toHtml (blogPostPostdate post_apZp));
.... }
If I change Day to Text, everything works as I expect. I'm not sure why Yesod can't deal with a Day since it has a dayField in Yesod.Form.Fields that I would expect to handle this. I figure this is something simple, but I can't seem to determine what I need to do to fix this error.
It appears there is no instance for ToMarkup for the Date datatype.
You could supply an instance yourself:
instance ToMarkup Date where
toMarkup = toMarkup . show
Which turns your date into a string and then converts it to Markup. If the default show instance doesn't fit your needs you could supply a formatter yourself and put it in the place of show.
I want to create a service who generates its HTML according to the parameter given and a map. Given the parameter, the service search in the map for the html, and a function to launch on client side.
type sample =
(string (* little text *)*
Html5_types.html Eliom_content.Html5.elt (* html page *) *
(unit -> unit)(* Demonstration function *))
Given that the function is to be launched on client side, I insert it in the map as a client value :
{client{
let demo_function = ignore (Ojquery.add_html
(Ojquery.jQ "li") "<p id='test1'>new paragraph</p>") }}
let get_samples () =
let samples_map = Samples.empty in
let samples_map = Samples.add "add_html"
("text",
(Eliom_tools.F.html
(** html stuff **)
),
{unit->unit{demo_function}}) samples_map in
samples_map
And then I register the service like this :
let sample_service =
Eliom_service.service
~path:["examples"]
~get_params:Eliom_parameter.(string "entry")
()
let () =
Examples_app.register
~service:sample_service
(fun (entry) () ->
try
(let entry = Samples.find entry samples_map in
let html = ((function (name, html, func) -> html) entry) in
let func = ((function (name, html, func) -> func) entry) in
ignore {unit{%func ()}};
Lwt.return (html))
with Not_found -> Lwt.return (not_found)
)
The rest of the code is pretty much only the result of a classic eliom-distillery, with the inclusion of the ojquery package for the client function used.
The compilation phase goes smoothly, but when I try to launch the server, I get the following error message :
ocsigenserver: main: Fatal - Error in configuration file: Error while parsing configuration file: Eliom: while loading local/lib/examples/examples.cma: Failure("That function cannot be called here because it needs information about the request or the site.")
My first guess was that it is due to the fact that I store client values outside of a service, but is there any way to store this kind of values on the server?
I tried to wrap them in regular functions :
let demo_serv_func () = {unit{demo_client_func ()}}
But the problem remained...
I found the issue. The problem was not because I stored client functions, but because I used Eliom_tools.F.html outside of a service.
It happens that Eliom_tools needs the context of the service to function, and since I was storing it outside of the service, it could not work.
I solved the issue by using Eliom_tools inside the service, and storing the body of the HTML page in the map.